Administrative Monetary Penalty C005
" "Person failed to keep the prescribed records for the " "prescribed period.
" "| First | $500 |
"""Unit tests for the AMPS Master Penalty Document ingester (canlex/amps.py).
Offline only. The ingester is a full rebuild, so a run that loses its network
half way through -- or an index CBSA rebuilds into something the link regex no
longer matches -- used to write the shortfall straight over the stored corpus.
These cover the module's own half of the fix: which contraventions count as
"failed this run", and that the identity used to preserve them is the same one
parse_page stamps on a chunk.
"""
import contextlib
import io
import json
import tempfile
import unittest
from pathlib import Path
from unittest import mock
from canlex import amps
class PreserveFailedTests(unittest.TestCase):
STORED = [{"section": "C005", "text": "records not kept"},
{"section": "C348", "text": "no advance data"}]
def test_unfetchable_contravention_keeps_its_last_good_chunk(self):
chunks, preserved = amps.preserve_failed(
[], [("c005", "ValueError: empty response")], self.STORED)
self.assertEqual(preserved, ["C005"])
self.assertEqual([c["text"] for c in chunks], ["records not kept"])
def test_index_codes_are_lower_case_but_sections_are_not(self):
# The whole preserve step turns on this: build() collects the index's
# lower-case c-number, a chunk carries it upper-cased.
_chunks, preserved = amps.preserve_failed([], [("c348", "404")],
self.STORED)
self.assertEqual(preserved, ["C348"])
def test_contravention_dropped_upstream_is_not_resurrected(self):
# C348 vanished from the index rather than failing; it stays gone.
chunks, preserved = amps.preserve_failed([], [("c005", "404")],
self.STORED)
self.assertEqual(preserved, ["C005"])
self.assertNotIn("C348", [c["section"] for c in chunks])
def test_freshly_scraped_chunk_wins_over_the_stored_copy(self):
fresh = [{"section": "C005", "text": "new penalty amounts"}]
chunks, preserved = amps.preserve_failed(fresh, [("c005", "404")],
self.STORED)
self.assertEqual((chunks, preserved), (fresh, []))
def test_contravention_we_never_had_cannot_be_preserved(self):
chunks, preserved = amps.preserve_failed([], [("c999", "404")],
self.STORED)
self.assertEqual((chunks, preserved), ([], []))
def test_a_clean_run_preserves_nothing(self):
fresh = [{"section": "C005", "text": "x"}]
chunks, preserved = amps.preserve_failed(fresh, [], self.STORED)
self.assertEqual((chunks, preserved), (fresh, []))
def test_total_scrape_failure_restores_the_whole_corpus(self):
# Every page erroring is the shape of the outage the guard is for: the
# stored corpus survives intact instead of being written away.
failed = [("c005", "timeout"), ("c348", "timeout")]
chunks, preserved = amps.preserve_failed([], failed, self.STORED)
self.assertEqual(preserved, ["C005", "C348"])
self.assertEqual(len(chunks), len(self.STORED))
class ChunkIdentityTests(unittest.TestCase):
"""preserve_failed keys on `section`; parse_page must keep filling it."""
HTML = (" Person failed to keep the prescribed records for the "
"prescribed period. Person failed to keep the prescribed records for the "
"prescribed period.Administrative Monetary Penalty C005
"
"First $500 Administrative Monetary Penalty C005
"
"