-
Notifications
You must be signed in to change notification settings - Fork 2
/
test_opinions.py
292 lines (244 loc) · 11.4 KB
/
test_opinions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
import pytest
from authorityspoke.entities import Entity
from authorityspoke.facts import Fact
from authorityspoke.io import anchors, loaders, readers
from authorityspoke.opinions import Opinion
class TestOpinions:
def test_opinion_features(self, make_decision):
assert make_decision["watt"].court == "9th-cir"
assert make_decision["watt"].citations[0].cite == "388 F.2d 853"
def test_repr(self, make_opinion):
assert "HAMLEY, Circuit Judge" in repr(make_opinion["watt_majority"])
def test_repr_excludes_text(self, make_opinion):
"""
reprs would be way too long if they could contain the
full opinion text.
"""
assert "text" not in repr(make_opinion["watt_majority"])
def test_opinion_author(self, make_opinion):
assert make_opinion["watt_majority"].author == "HAMLEY, Circuit Judge"
assert make_opinion["brad_majority"].author == "BURKE, J."
assert (
make_opinion["brad_concurring-in-part-and-dissenting-in-part"].author
== "TOBRINER, J."
)
def test_opinion_holding_list(self, make_opinion, real_holding):
watt = make_opinion["watt_majority"]
h3_specific = real_holding["h3"]
watt.posit(h3_specific)
assert h3_specific in watt.holdings
def test_opinion_entity_list(
self, make_opinion, real_holding, make_entity, make_evidence
):
watt = make_opinion["watt_majority"]
h = real_holding
e = make_entity
watt.posit(h["h1"], context=(e["motel"], e["watt"]))
watt.posit(h["h2"], context=(e["trees"], e["motel"]))
watt.posit(
h["h3"],
context=(
make_evidence["generic"],
e["motel"],
e["watt"],
e["trees"],
e["tree_search"],
),
)
watt.posit(
h["h4"], context=(e["trees"], e["tree_search"], e["motel"], e["watt"])
)
assert make_entity["watt"] in make_opinion["watt_majority"].generic_factors
def test_opinion_date(self, make_decision):
"""
This no longer tests whether two Opinions from the same Decision
have the same date, because the date field has been moved to the
Decision class.
"""
assert make_decision["watt"].date < make_decision["brad"].date
def test_opinion_string(self, make_opinion):
opinion = make_opinion["cardenas_majority"]
assert str(opinion).lower() == "majority opinion by bird, c. j."
class TestOpinionText:
def test_opinion_text(self, make_opinion):
assert (
"Feist responded that such efforts were economically "
+ "impractical and, in any event, unnecessary"
) in make_opinion["feist_majority"].text
def test_opinion_text_anchor(self, make_opinion_with_holding):
feist = make_opinion_with_holding["feist_majority"]
assert any(
"generally" in anchor.exact
for anchor in feist.get_anchors(feist.holdings[1])
)
def test_opinion_factor_text_anchor(self, make_opinion_with_holding):
feist = make_opinion_with_holding["feist_majority"]
anchors = feist.get_anchors(feist.holdings[0])
assert all(
"No one may claim originality" not in anchor.exact for anchor in anchors
)
assert any("as to facts" in anchor.exact for anchor in anchors)
def test_select_opinion_text_for_factor(self, make_opinion_with_holding):
oracle = make_opinion_with_holding["oracle_majority"]
factor = oracle.holdings[0].outputs[0]
anchor = oracle.factors[factor][0]
selected = oracle.select_text(selector=anchor)
assert selected == "copyright protection."
def test_select_opinion_text_for_enactment(self, make_opinion_with_holding):
oracle = make_opinion_with_holding["oracle_majority"]
enactment = oracle.holdings[0].enactments[0]
anchor = oracle.factors[enactment][0]
selected = oracle.select_text(selector=anchor)
assert selected == "17 U.S.C. § 102(a)"
def test_select_opinion_text_for_holding(self, make_opinion_with_holding):
oracle = make_opinion_with_holding["oracle_majority"]
holding = oracle.holdings[0]
anchor = oracle.holding_anchors[holding][0]
selected = oracle.select_text(selector=anchor)
assert selected == "must be “original” to qualify"
class TestOpinionHoldings:
def test_positing_non_rule_error(self, make_opinion, make_procedure):
with pytest.raises(TypeError):
make_opinion["watt_majority"].posit(make_procedure["c1"])
def test_error_posit_with_no_rule_source(self, make_opinion):
with pytest.raises(TypeError):
make_opinion["watt_majority"].posit()
def test_posit_rule(self, make_opinion, make_rule, make_holding):
"""
"Positing" a Rule causes the Rule to be converted to a Holding first.
So the Opinion implies the corresponding Holding.
"""
watt = make_opinion["watt_majority"]
watt.posit(make_rule["h1"])
assert watt.implies(make_holding["h1"])
def test_new_context_non_iterable_changes(self, make_opinion, make_holding):
"""
The context here (a Factor outside an iterable) only changes the first
generic factor of the Rule being posited, which may not be what the user
expects.
"""
brad = make_opinion["brad_majority"]
brad.posit(make_holding["h1"], context=Entity("House on Haunted Hill"))
assert "Haunted Hill" in str(brad.holdings[0])
def test_new_context_naming_nonexistent_factor(self, make_opinion, make_holding):
"""
The context here (a Factor outside an iterable) only changes the first
generic factor of the Rule being posited, which may not be what the user
expects.
"""
brad = make_opinion["brad_majority"]
with pytest.raises(ValueError):
brad.posit(
make_holding["h1"],
context=(Entity("House on Haunted Hill"), "nonexistent factor"),
)
def test_new_context_creates_equal_rule(self, make_opinion, make_regime):
watt = make_opinion["watt_majority"]
brad = make_opinion["brad_majority"]
watt.clear_holdings()
watt_raw = loaders.load_holdings("holding_watt.json")
watt.posit(readers.read_holdings(watt_raw, regime=make_regime))
brad.clear_holdings()
brad_raw = loaders.load_holdings("holding_brad.json")
brad.posit(readers.read_holdings(brad_raw, regime=make_regime))
context_pairs = {
"proof of Bradley's guilt": "proof of Wattenburg's guilt",
"Bradley": "Wattenburg",
"officers' search of the yard": "officers' search of the stockpile",
"Bradley's marijuana patch": "the stockpile of trees",
}
watt.posit(brad.holdings[0], context_pairs)
assert watt.holdings[-1].means(brad.holdings[0])
def test_new_context_inferring_factors_to_change(self, make_opinion, make_regime):
"""
This changes watt's holdings; may break tests below.
"""
watt = make_opinion["watt_majority"]
brad = make_opinion["brad_majority"]
watt.clear_holdings()
watt_raw = loaders.load_holdings("holding_watt.json")
watt.posit(readers.read_holdings(watt_raw, regime=make_regime))
brad.clear_holdings()
brad_raw = loaders.load_holdings("holding_brad.json")
brad.posit(readers.read_holdings(brad_raw, regime=make_regime))
context_items = [
"proof of Wattenburg's guilt",
"Wattenburg",
"officers' search of the stockpile",
"Hideaway Lodge",
"the stockpile of trees",
]
watt.posit(brad.holdings[0], context=context_items)
assert watt.holdings[-1].means(brad.holdings[0])
class TestOpinionFactors:
def test_only_one_factor_with_same_content(self, make_opinion_with_holding):
"""
Tests that a particular Factor appears only once, and that all
three of the text anchors for that Factor appear in the value
for the Factor in Opinion.factors.
"""
oracle = make_opinion_with_holding["oracle_majority"]
scenes_a_faire = [
factor
for factor in oracle.factors.items()
if isinstance(factor[0], Fact)
and factor[0].short_string
== "the fact that <the Java API> was a scene a faire"
]
assert len(scenes_a_faire) == 1 # 1 Factor
assert len(scenes_a_faire[0][1]) == 3
class TestImplication:
def test_no_implication(self, make_opinion_with_holding):
watt = make_opinion_with_holding["watt_majority"]
brad = make_opinion_with_holding["brad_majority"]
assert not watt >= brad
def test_posit_list_of_holdings_and_imply(self, make_opinion, make_regime):
watt = make_opinion["watt_majority"]
brad = make_opinion["brad_majority"]
some_rules_raw = loaders.load_holdings(filename="holding_watt.json")
some_rules = readers.read_holdings(some_rules_raw, regime=make_regime)
for case in (watt, brad):
case.clear_holdings()
case.posit(some_rules[:3])
watt.posit(some_rules[3])
assert watt > brad
assert not brad >= watt
def test_opinion_implies_holding(self, make_opinion, make_holding):
watt = make_opinion["watt_majority"]
watt.posit(make_holding["h2_invalid_undecided"])
assert watt >= make_holding["h2_undecided"]
assert watt > make_holding["h2_undecided"]
def test_opinion_does_not_imply_holding(self, make_opinion, make_holding):
watt = make_opinion["watt_majority"]
watt.clear_holdings()
watt.posit(make_holding["h2_irrelevant_inputs_undecided"])
assert not watt >= make_holding["h2_undecided"]
assert not watt > make_holding["h2_undecided"]
class TestContradiction:
def test_contradiction_of_holding(
self, make_opinion_with_holding, make_enactment, make_holding
):
assert make_opinion_with_holding["watt_majority"].contradicts(
make_holding["h2_output_false_ALL_MUST"] + make_enactment["search_clause"]
)
def test_explain_opinion_contradicting_holding(self, make_opinion_with_holding):
oracle = make_opinion_with_holding["oracle_majority"]
lotus = make_opinion_with_holding["lotus_majority"]
explanation = oracle.explain_contradiction(lotus.holdings[6])
assert "an explanation" in str(explanation).lower()
def test_contradiction_of_decision(
self, make_opinion_with_holding, make_decision_with_holding
):
assert make_opinion_with_holding["oracle_majority"].contradicts(
make_decision_with_holding["lotus"]
)
def test_explain_opinion_contradicting_decision(
self, make_opinion_with_holding, make_decision_with_holding
):
oracle_majority = make_opinion_with_holding["oracle_majority"]
lotus = make_decision_with_holding["lotus"]
explanation = oracle_majority.explain_contradiction(lotus)
assert "an explanation" in str(explanation).lower()
def test_error_contradiction_with_procedure(self, make_opinion, make_procedure):
with pytest.raises(TypeError):
make_opinion["watt_majority"].contradicts(make_procedure["c1"])