json-diff-tool / utils.py
Amanda Torres
initial commit
e197abb
import hashlib
import hmac
import re
import secrets
import string
from datetime import datetime, timezone
from typing import Any, Optional
EMAIL_RE = re.compile(r'^[\w.+-]+@[\w-]+\.[\w.-]+$')
def hash_password(pw: str, salt: Optional[str] = None) -> tuple[str, str]:
if salt is None:
salt = secrets.token_hex(16)
digest = hashlib.pbkdf2_hmac("sha256", pw.encode(), salt.encode(), 200_000)
return digest.hex(), salt
def verify_password(pw: str, digest: str, salt: str) -> bool:
computed, _ = hash_password(pw, salt)
return hmac.compare_digest(computed, digest)
def generate_token(n: int = 32) -> str:
return "".join(secrets.choice(string.ascii_letters + string.digits) for _ in range(n))
def slugify(text: str, max_len: int = 60) -> str:
text = text.lower().replace(" ", "-")
text = re.sub(r"[^\w-]", "", text)
return text[:max_len].strip("-")
def truncate(text: str, n: int = 120) -> str:
return text if len(text) <= n else text[:n - 3] + "..."
def utcnow() -> str:
return datetime.now(timezone.utc).isoformat()
def parse_bool(v: Any) -> bool:
if isinstance(v, bool):
return v
return str(v).strip().lower() in ("1", "true", "yes", "on")
def chunk(lst: list, size: int) -> list[list]:
return [lst[i:i + size] for i in range(0, len(lst), size)]
def deep_merge(base: dict, override: dict) -> dict:
out = dict(base)
for k, v in override.items():
if k in out and isinstance(out[k], dict) and isinstance(v, dict):
out[k] = deep_merge(out[k], v)
else:
out[k] = v
return out
def flatten(nested: list) -> list:
result = []
for item in nested:
if isinstance(item, list):
result.extend(flatten(item))
else:
result.append(item)
return result