Example CSV validations#

Demonstrating validate_csv:

This notebook shows simple, self-contained examples of the validate_csv function.

It supports two modes:

  1. Direct validation of a local path, Path, or URL → returns True / False

  2. Decorator mode → the decorated function runs only after the CSV argument passes validation (raises CsvValidationError on failure)

Correct import (the package also provides a similar validate_json):

from fileaudit.csv_check import validate_csv, CsvValidationError
# Install if needed (already present in many environments)
# !pip install fileaudit -q

from pathlib import Path
from fileaudit.csv_check import (
    validate_csv,
    CsvValidationError,
    DEFAULT_MAX_FILE_SIZE,
    DEFAULT_MAX_ROWS,
    DEFAULT_MAX_COLUMNS,
)

print("Defaults:")
print(f"  max_file_size = {DEFAULT_MAX_FILE_SIZE} bytes ({DEFAULT_MAX_FILE_SIZE / 1024 / 1024:.1f} MB)")
print(f"  max_rows      = {DEFAULT_MAX_ROWS}")
print(f"  max_columns   = {DEFAULT_MAX_COLUMNS}")
Defaults:
  max_file_size = 10485760 bytes (10.0 MB)
  max_rows      = 100000
  max_columns   = 1000

1. Direct validation of a local CSV file#

validate_csv(path) returns True on success and False on failure.

# Create a simple valid CSV
valid_path = Path("valid_demo.csv")
valid_path.write_text("name,age,city\nAlice,30,NYC\nBob,25,London\n", encoding="utf-8")

result = validate_csv(valid_path)
print(f"validate_csv({valid_path!r}) → {result}")

# Also works with a plain string path
print(f"validate_csv('valid_demo.csv') → {validate_csv('valid_demo.csv')}")
validate_csv(PosixPath('valid_demo.csv')) → True
validate_csv('valid_demo.csv') → True

2. Reject formula injection (default behaviour)#

Fields that look like spreadsheet formulas (=, +, -, @ …) are rejected when reject_formula_injection=True (the default).

formula_path = Path("formula_demo.csv")
formula_path.write_text(
    "name,formula,score\n"
    "Alice,=2+2,90\n"
    "Bob,normal,85\n",
    encoding="utf-8",
)

print("With reject_formula_injection=True (default):")
print("  →", validate_csv(formula_path))

print("\nWith reject_formula_injection=False:")
print("  →", validate_csv(formula_path, reject_formula_injection=False))
With reject_formula_injection=True (default):
Exception: FileAudit Security Validation Failed - Rejected field at row 2, column 2: possible spreadsheet formula injection
  → False

With reject_formula_injection=False:
  → True

3. Size / shape limits#

You can restrict file size, number of rows, columns, etc.

# A CSV with more rows than our limit
many_rows = Path("many_rows_demo.csv")
with many_rows.open("w", encoding="utf-8", newline="") as f:
    f.write("id,value\n")
    for i in range(15):
        f.write(f"{i},val{i}\n")

print("File has 15 data rows + header.")
print("max_rows=10 →", validate_csv(many_rows, max_rows=10))
print("max_rows=20 →", validate_csv(many_rows, max_rows=20))
print("max_columns=1 →", validate_csv(many_rows, max_columns=1))  # two columns present
print("max_file_size=50 (bytes) →", validate_csv(many_rows, max_file_size=50))
File has 15 data rows + header.
Exception: FileAudit Security Validation Failed - CSV contains more than 10 rows
max_rows=10 → False
max_rows=20 → True
Exception: FileAudit Security Validation Failed - Rejected row 1: contains 2 columns, exceeding maximum of 1
max_columns=1 → False
Exception: FileAudit Security Validation Failed - File size exceeds maximum of 50 bytes
max_file_size=50 (bytes) → False

4. Decorator usage – first argument is the CSV path#

When used as @validate_csv (or @validate_csv()), the first parameter of the decorated function is treated as the CSV path.

@validate_csv
def process_csv(csv_path):
    """Simple processing that only runs after validation succeeds."""
    text = Path(csv_path).read_text(encoding="utf-8")
    return f"Processed {len(text.splitlines())} lines from {csv_path}"

# Valid file → function is called
print(process_csv("valid_demo.csv"))

# Invalid file (formula) → CsvValidationError is raised
try:
    print(process_csv("formula_demo.csv"))
except CsvValidationError as e:
    print(f"Caught expected error: {type(e).__name__}: {e}")
Processed 3 lines from valid_demo.csv
Caught expected error: CsvValidationError: FileAudit Security Validation Failed - Rejected field at row 2, column 2: possible spreadsheet formula injection

5. Decorator with explicit argument name and custom limits#

@validate_csv(
    "input_file",                 # name of the parameter that holds the CSV path
    max_rows=5,
    reject_formula_injection=True,
)
def analyse(input_file, extra_info="none"):
    return f"Analysed {input_file} (extra={extra_info})"

print(analyse("valid_demo.csv", extra_info="demo"))

# Too many rows
try:
    analyse("many_rows_demo.csv")
except CsvValidationError as e:
    print(f"Caught expected error (max_rows): {e}")
Analysed valid_demo.csv (extra=demo)
Caught expected error (max_rows): FileAudit Security Validation Failed - CSV contains more than 5 rows

6. Decorator with @validate_csv() (empty call) – same as bare @validate_csv#

@validate_csv()
def count_rows(path):
    return sum(1 for _ in Path(path).open(encoding="utf-8"))

print("Row count (including header):", count_rows("valid_demo.csv"))
Row count (including header): 3

7. Control characters rejection#

By default reject_control_characters=True rejects most C0 control characters.

# Create a file containing a control character (ASCII 0x01)
ctrl_path = Path("ctrl_demo.csv")
# Write binary-ish content carefully
ctrl_path.write_bytes(b"name,note\nAlice,hello\x01world\nBob,ok\n")

print("reject_control_characters=True  →", validate_csv(ctrl_path))
print("reject_control_characters=False →", validate_csv(ctrl_path, reject_control_characters=False))
Exception: FileAudit Security Validation Failed - Rejected field at row 2, column 2: contains control character U+0001
reject_control_characters=True  → False
reject_control_characters=False → True

8. Using a pathlib.Path object and checking return values#

p = Path("valid_demo.csv")
assert validate_csv(p) is True
assert validate_csv(Path("formula_demo.csv")) is False

print("All direct-mode assertions passed.")
Exception: FileAudit Security Validation Failed - Rejected field at row 2, column 2: possible spreadsheet formula injection
All direct-mode assertions passed.

Cleanup (optional)#

for f in Path(".").glob("*_demo.csv"):
    f.unlink(missing_ok=True)
print("Demo CSV files removed.")
Demo CSV files removed.

Summary of capabilities demonstrated#

Feature

Example

Direct validation (local path / Path)

validate_csv("file.csv")True/False

Formula-injection protection

default reject_formula_injection=True

Control-character rejection

default reject_control_characters=True

Size / row / column limits

max_file_size, max_rows, max_columns, …

Decorator (first arg)

@validate_csv / @validate_csv()

Decorator (named arg + options)

@validate_csv("input_file", max_rows=5)

Error signalling

CsvValidationError in decorator mode