-
Notifications
You must be signed in to change notification settings - Fork 2
/
test_enactments.py
357 lines (289 loc) · 13.8 KB
/
test_enactments.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
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
import datetime
import os
from anchorpoint.textselectors import TextQuoteSelector, TextSelectionError
from dotenv import load_dotenv
from legislice.download import Client
from legislice.citations import CodeLevel
from legislice.enactments import Enactment
from legislice.groups import EnactmentGroup
from legislice.schemas import EnactmentSchema
from nettlesome.entities import Entity
from nettlesome.predicates import Predicate
from nettlesome.statements import Statement
import pytest
from authorityspoke.io import loaders, readers, schemas_yaml, dump
from authorityspoke.io.fake_enactments import FakeClient
load_dotenv()
TOKEN = os.getenv("LEGISLICE_API_TOKEN")
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, insteaid 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")
art_3.select(selector)
assert art_3.text.startswith("To promote")
assert art_3.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_make_enactment_from_dict_with_text_split(self, fake_usc_client):
fourth_a = fake_usc_client.read_from_json(
{
"node": "/us/const/amendment/IV",
"text": "and|the persons or things|to be seized.",
}
)
assert fourth_a.selected_text() == "…the persons or things…"
def test_passage_from_imported_statute(self, fake_usc_client):
oracle_majority = loaders.load_and_read_decision(f"oracle_h.json").majority
loaded = loaders.load_holdings("holding_oracle.json")
holdings = readers.read_holdings(loaded, client=fake_usc_client)
oracle_majority.posit(holdings)
despite_text = str(list(oracle_majority.holdings)[5])
assert "In no case does copyright protection " in despite_text
def test_short_passage_from_uslm_code(self, fake_usc_client):
"""Also tests adding the missing initial "/" in ``path``."""
method = fake_usc_client.read_from_json(
{
"node": "us/usc/t17/s102/b",
"prefix": "process, system,",
"suffix": ", concept, principle",
},
)
assert method.selected_text() == "…method of operation…"
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("$defendant stole $object")
stole_fact = Statement(
stole_predicate, terms=[Entity("Alice"), Entity("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):
with pytest.raises(TextSelectionError):
_ = Enactment(
node="/us/const/amendment/IV",
selection=make_selector["bad_selector"],
heading="",
content="Not the same text as in the selector",
start_date="2000-01-01",
)
# 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")
copyright_clause.select(None)
securing_for_authors = copyright_clause + (
"To promote the Progress of Science and "
"useful Arts, by securing for limited Times to Authors"
)
and_inventors = copyright_clause + "and Inventors"
right_to_writings = (
copyright_clause + "the exclusive Right to their respective Writings"
)
to_combine = [
copyright_statute,
securing_for_authors,
and_inventors,
right_to_writings,
]
combined = EnactmentGroup(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([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(TypeError):
print(e_search_clause + watt_factor["f3"])
def test_cannot_add_enactment_to_statement(self, e_search_clause):
statement = Statement(
Predicate("$person committed a murder"), terms=Entity("Al")
)
with pytest.raises(TypeError):
statement + e_search_clause
def test_cannot_add_statement_to_enactment(self, e_search_clause):
statement = Statement(
Predicate("$person committed a murder"), terms=Entity("Al")
)
with pytest.raises(TypeError):
e_search_clause + statement
def test_cant_add_enactment_that_is_not_ancestor_or_descendant(
self, e_search_clause, e_copyright
):
with pytest.raises(ValueError):
e_search_clause + e_copyright
class TestDump:
client = Client(api_token=TOKEN)
@pytest.mark.vcr
def test_dump_dict(self):
enactment = self.client.read("/us/const/article/I/8/8")
d = dump.to_dict(enactment)
start = d["selection"][0]["start"]
end = d["selection"][0]["end"]
text_selection = d["text_version"]["content"][start:end]
assert "Science and useful Arts" in text_selection
def test_dump_json(self, fake_beard_client):
provision = fake_beard_client.read_from_json({"node": "/test/acts/47/6A"})
dumped_provision = dump.to_json(provision)
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 = dump.to_dict(provision)
new = self.client.read_from_json(dumped_provision)
assert new.node == "/test/acts/47/6A"
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_selector_text_split(self):
data = {"text": "process, system,|method of operation|, concept, principle"}
schema = schemas_yaml.SelectorSchema()
selector = schema.load(data)
assert selector.exact.startswith("method")
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):
with pytest.raises(TextSelectionError):
_ = fake_usc_client.read_from_json(
{
"node": "/us/const/amendment/XV/1",
"exact": "due process",
}
)
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, holding_anchors, _, _ = loaders.read_anchored_holdings_from_file(
"holding_feist.json", client=client
)
assert len(holding_anchors[6]) == 2