Update web/core/utils.py

This commit is contained in:
Joshua Laymon 2025-08-13 15:02:10 +00:00
parent 445da3523b
commit d52b89ee3f

View File

@ -7,7 +7,56 @@ from typing import Dict, Any
from django.db import transaction from django.db import transaction
from core.models import Entry from core.models import Entry
# --- Search helpers restored -------------------------------------------------
from typing import List
def terms(q: str) -> List[str]:
"""
Split a query string into search terms.
- Quoted phrases are kept together: `"good shepherd"`
- Unquoted text splits on whitespace.
- Empty/whitespace-only input returns [].
"""
if not q:
return []
# capture "quoted phrases" OR bare tokens
rx = re.compile(r'"([^"]+)"|(\S+)')
out = []
for m in rx.finditer(q):
phrase = m.group(1) if m.group(1) is not None else m.group(2)
t = (phrase or "").strip()
if t:
out.append(t)
return out
def has_wildcards(s: str) -> bool:
"""
True if user supplied * or ? wildcards (FileMaker-style).
We also treat SQL wildcards % and _ as wildcards if present.
"""
if not s:
return False
return any(ch in s for ch in ("*", "?", "%", "_"))
def wildcard_to_regex(s: str) -> str:
"""
Convert * and ? to a case-insensitive regex fragment suitable for Django's iregex.
- Escapes regex meta first, then replaces \* -> .* and \? -> .
- Wraps with '.*' so it matches anywhere (like icontains).
Example: 'lov* you?' -> '(?i).*lov.* you..*'
(The view should use iregex so (?i) or case-insensitive flag applies.)
"""
if s is None:
s = ""
# Escape regex specials, then un-escape our wildcards into regex
pat = re.escape(s)
pat = pat.replace(r"\*", ".*").replace(r"\?", ".")
# Match anywhere by default
pat = f".*{pat}.*"
# collapse consecutive ".*.*"
pat = re.sub(r"(?:\.\*){2,}", ".*", pat)
return pat
# -----------------------------------------------------------------------------
# ============================== # ==============================
# Helpers # Helpers
# ============================== # ==============================