redaction 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
redaction/__init__.py
ADDED
redaction/cli.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PII redaction script using Microsoft Presidio.
|
|
3
|
+
Processes a file line by line and creates an output file with redacted content.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
# Import Presidio
|
|
11
|
+
try:
|
|
12
|
+
from presidio_analyzer import AnalyzerEngine
|
|
13
|
+
from presidio_anonymizer import AnonymizerEngine
|
|
14
|
+
except ImportError:
|
|
15
|
+
print("Please install presidio: pip install presidio-analyzer presidio-anonymizer")
|
|
16
|
+
sys.exit(1)
|
|
17
|
+
|
|
18
|
+
# Import rich_argparse for better CLI output
|
|
19
|
+
try:
|
|
20
|
+
from rich_argparse import RichHelpFormatter
|
|
21
|
+
except ImportError:
|
|
22
|
+
print("Please install rich_argparse: pip install rich-argparse")
|
|
23
|
+
RichHelpFormatter = argparse.RawDescriptionHelpFormatter
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class PresidioRedactor:
|
|
27
|
+
"""Handles PII redaction using Microsoft Presidio."""
|
|
28
|
+
|
|
29
|
+
def __init__(self):
|
|
30
|
+
"""Initialize Presidio engines."""
|
|
31
|
+
self.presidio_analyzer = AnalyzerEngine()
|
|
32
|
+
self.presidio_anonymizer = AnonymizerEngine()
|
|
33
|
+
|
|
34
|
+
def redact(self, text):
|
|
35
|
+
"""Redact PII using Microsoft Presidio."""
|
|
36
|
+
# Analyze the text for PII
|
|
37
|
+
results = self.presidio_analyzer.analyze(text=text, language="en")
|
|
38
|
+
|
|
39
|
+
# Anonymize the detected PII if any found
|
|
40
|
+
if results:
|
|
41
|
+
anonymized = self.presidio_anonymizer.anonymize(
|
|
42
|
+
text=text, analyzer_results=results
|
|
43
|
+
)
|
|
44
|
+
return anonymized.text
|
|
45
|
+
return text
|
|
46
|
+
|
|
47
|
+
def process_file(self, input_file, output_file=None):
|
|
48
|
+
"""Process a file line by line using Presidio."""
|
|
49
|
+
input_path = Path(input_file)
|
|
50
|
+
if not input_path.exists():
|
|
51
|
+
print(f"Error: Input file '{input_file}' not found.")
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
# Determine output file name
|
|
55
|
+
output_path = Path(output_file or f"{input_path.stem}_redacted.txt")
|
|
56
|
+
|
|
57
|
+
print(f"Processing file: {input_path}")
|
|
58
|
+
print(f"Output file: {output_path}\n")
|
|
59
|
+
|
|
60
|
+
# Process the file
|
|
61
|
+
with open(input_path, "r", encoding="utf-8") as infile, \
|
|
62
|
+
open(output_path, "w", encoding="utf-8") as outfile:
|
|
63
|
+
|
|
64
|
+
line_count = 0
|
|
65
|
+
for line_num, line in enumerate(infile, 1):
|
|
66
|
+
line_content = line.rstrip("\n")
|
|
67
|
+
|
|
68
|
+
# Handle empty lines
|
|
69
|
+
if not line_content:
|
|
70
|
+
outfile.write("\n")
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
line_count += 1
|
|
74
|
+
|
|
75
|
+
# Apply Presidio redaction and write output
|
|
76
|
+
outfile.write(self.redact(line_content) + "\n")
|
|
77
|
+
|
|
78
|
+
# Progress indicator for large files
|
|
79
|
+
if line_num % 100 == 0:
|
|
80
|
+
print(f" Processed {line_num} lines...")
|
|
81
|
+
|
|
82
|
+
print(f"\nSuccessfully processed {line_count} non-empty lines.")
|
|
83
|
+
return True
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def main():
|
|
87
|
+
"""Main function to handle command-line arguments and run the redactor."""
|
|
88
|
+
parser = argparse.ArgumentParser(
|
|
89
|
+
prog="redact",
|
|
90
|
+
description="🕵️♂️ Redact PII from text files using Microsoft Presidio.",
|
|
91
|
+
formatter_class=RichHelpFormatter,
|
|
92
|
+
epilog="""
|
|
93
|
+
Examples:
|
|
94
|
+
redact input.txt
|
|
95
|
+
redact input.txt -o cleaned.txt
|
|
96
|
+
redact sensitive_data.txt -o /path/to/output/safe_data.txt
|
|
97
|
+
|
|
98
|
+
The script uses Microsoft Presidio to detect and redact personally identifiable information (PII)
|
|
99
|
+
including names, email addresses, phone numbers, SSNs, credit card numbers, and more.
|
|
100
|
+
""",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
parser.add_argument(
|
|
104
|
+
"input_file",
|
|
105
|
+
metavar="FILE",
|
|
106
|
+
help="Path to the input file to be redacted"
|
|
107
|
+
)
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
"-o",
|
|
110
|
+
"--output",
|
|
111
|
+
dest="output_file",
|
|
112
|
+
metavar="OUTPUT",
|
|
113
|
+
help="Output file name (default: <input>_redacted.txt)",
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
args = parser.parse_args()
|
|
117
|
+
|
|
118
|
+
# Initialize the redactor and process the file
|
|
119
|
+
print("Initializing Presidio...\n")
|
|
120
|
+
redactor = PresidioRedactor()
|
|
121
|
+
|
|
122
|
+
if redactor.process_file(args.input_file, args.output_file):
|
|
123
|
+
print("\nRedaction complete!")
|
|
124
|
+
print("Note: Always manually review the output file to ensure all sensitive data has been properly redacted.")
|
|
125
|
+
else:
|
|
126
|
+
sys.exit(1)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
if __name__ == "__main__":
|
|
130
|
+
main()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: redaction
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Simple redaction script
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: presidio-analyzer>=2.2.360
|
|
8
|
+
Requires-Dist: presidio-anonymizer>=2.2.360
|
|
9
|
+
Requires-Dist: rich-argparse>=1.7.1
|
|
10
|
+
|
|
11
|
+
# 🕵️ PII Redaction Tool
|
|
12
|
+
|
|
13
|
+
A no-nonsense (but kinda cool) script that wipes out personal info from text files using **Microsoft Presidio**.
|
|
14
|
+
|
|
15
|
+
Does not require Torch.
|
|
16
|
+
|
|
17
|
+
Tried **scrubadub** and **pii-codex**, but they didn't quite pass the vibe check — so this one gets the job done.
|
|
18
|
+
|
|
19
|
+
## 🚀 Usage
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install redaction
|
|
23
|
+
|
|
24
|
+
redact file.txt
|
|
25
|
+
redact file.txt -o output.txt
|
|
26
|
+
redact --help
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
* By default, the redacted version lands in the same directory as your input file.
|
|
30
|
+
* Use the `-o` flag to specify your own output file.
|
|
31
|
+
|
|
32
|
+
## ⚙️ Installation
|
|
33
|
+
|
|
34
|
+
With [uv](https://docs.astral.sh/uv/):
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv sync
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or the classic pip way:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install -e .
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then you're ready to redact like a pro.
|
|
47
|
+
All detected PII gets anonymized and saved into a clean, single output file — powered by **Microsoft Presidio** 🧠.
|
|
48
|
+
|
|
49
|
+
<br>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
redaction/__init__.py,sha256=TwRdNaC8ErWwxAGKH6nNtjrUCd1SIHcku6ua8wxT2p4,77
|
|
2
|
+
redaction/cli.py,sha256=hXTC3gQkug3LKSmbN-YSQZXPhqUuvs4NhH4pgtwkHrg,4136
|
|
3
|
+
redaction-0.1.1.dist-info/METADATA,sha256=GlvKqoaG2dBkq1I-bnSenQi87gBMm_-E4TLtHR1JE5w,1113
|
|
4
|
+
redaction-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
+
redaction-0.1.1.dist-info/entry_points.txt,sha256=F2LuWAksmF1UvO1gwxNkqh5oeF07FWYLijCckBwoGzk,46
|
|
6
|
+
redaction-0.1.1.dist-info/top_level.txt,sha256=VkZVTpgmoHK91-NVsRfo1uB4b7f0FX0MSAi1H5CRk4o,10
|
|
7
|
+
redaction-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
redaction
|