Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Notable changes to the `phileas-redact` package, most recent first.

## Unreleased

* The `streetAddress` filter no longer matches across a line break. The parts of an address were joined by `\s`, which includes line breaks, so a number at the end of one line and a word and a street type on the next were read as an address: in `Cedar Falls, IA 50613`, a blank line, and `Dear Dr. Rivera,`, the text from `50613` to `Dr` was detected, with `Dr` read as Drive. The parts are now joined by spaces and tabs, as in Phileas (Java), so an address on one line and the street line of a multi-line address block are found as before. Parts separated by other whitespace, such as a no-break space, no longer form an address. This is the parity port of the Phileas (Java) fix for philterd/phileas#474.
* The `ssn` filter no longer detects the `NN-NNNNNNN` form. That shape is an Employer Identification Number, not a Social Security Number, and is already covered by the `ein` filter. A policy that enables only `ssn` therefore no longer detects values such as `12-3456789`; enable `ein` to detect them. SSN forms (`NNN-NN-NNNN`, `NNN NN NNNN`, and nine digits with no hyphen) are unchanged.

## Version 1.1.0
Expand Down
5 changes: 4 additions & 1 deletion phileas/filters/street_address_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
from .base import BaseFilter, FilterType


# The parts are joined by spaces and tabs only, as in the Java filter, so a match does not
# run from one line into the next (a ZIP code at the end of a line and "Dear Dr." on the
# next are not an address).
_PATTERNS = [
re.compile(
r"\b\d{1,5}\s+(?:[A-Za-z0-9#.,\-]+\s+){1,4}"
r"\b\d{1,5}[ \t]+(?:[A-Za-z0-9#.,\-]+[ \t]+){1,4}"
r"(?:Street|St|Avenue|Ave|Boulevard|Blvd|Road|Rd|Lane|Ln|Drive|Dr|Court|Ct|Place|Pl|Way|Circle|Cir|Terrace|Ter|Trail|Trl)\b",
re.IGNORECASE,
),
Expand Down
23 changes: 23 additions & 0 deletions tests/test_street_address_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,26 @@ def test_long_street_name_within_word_limit(street_filter):
assert spans[0].text == addr


def test_no_match_across_line_breaks(street_filter):
# A ZIP code at the end of a line and "Dear Dr." on the next line are not an address.
text = "Address: 214 Juniper Court, Cedar Falls, IA 50613\n\nDear Dr. Rivera,"
spans = street_filter.detect(text)
assert [s.text for s in spans] == ["214 Juniper Court"]


@pytest.mark.parametrize(
"text,expected",
[
("214 Juniper Court\nCedar Falls, IA 50613", "214 Juniper Court"),
("123 Main St Apt 4B\r\nSpringfield, IL 62704", "123 Main St"),
("Jane Doe\n1 Martin Luther King Jr Blvd\nAtlanta, GA 30303", "1 Martin Luther King Jr Blvd"),
],
)
def test_street_line_of_address_block(street_filter, text, expected):
spans = street_filter.detect(text)
assert [s.text for s in spans] == [expected]


def test_default_context_returns_results(street_filter):
spans = street_filter.detect("123 Main Street", context="default")
assert len(spans) == 1
Expand Down Expand Up @@ -146,6 +166,9 @@ def test_custom_context_still_detects(street_filter):
"123 Main Streets", # trailing 's' breaks the suffix word boundary
"123 Main Streetss",
"123456 Main Street", # number has six digits (exceeds \\d{1,5})
"Cedar Falls, IA 50613\nDear Dr. Rivera,", # parts on different lines
"Cedar Falls, IA 50613\r\nDear Dr. Rivera,",
"Unit 12\nMain Street",
],
)
def test_no_detection(street_filter, text):
Expand Down