MCPcopy Create free account
hub / github.com/Dispatcharr/Dispatcharr / parse_text_query

Function parse_text_query

apps/epg/query_utils.py:35–137  ·  view source on GitHub ↗

Parse a search expression into a Q object. Supports: - AND / OR (case-insensitive) between bare terms. - Double-quoted phrases (atomic; never split on operators). - Parenthetical grouping with arbitrary nesting. - Regex mode (entire raw value is treated as a single regex

(field_name, raw_value, use_regex=False, whole_words=False)

Source from the content-addressed store, hash-verified

33
34
35def parse_text_query(field_name, raw_value, use_regex=False, whole_words=False):
36 """Parse a search expression into a Q object.
37
38 Supports:
39 - AND / OR (case-insensitive) between bare terms.
40 - Double-quoted phrases (atomic; never split on operators).
41 - Parenthetical grouping with arbitrary nesting.
42 - Regex mode (entire raw value is treated as a single regex).
43 - Whole-word mode (each bare term anchored with word boundaries).
44
45 A bare value with no operators is matched as a single phrase via
46 icontains (or regex / whole-word as configured).
47 """
48 phrases = {}
49
50 def extract_quoted(text):
51 def replacer(m):
52 key = f'\x00P{len(phrases)}\x00'
53 phrases[key] = m.group(1)
54 return key
55 return re.sub(r'"([^"]*)"', replacer, text)
56
57 processed = extract_quoted(raw_value)
58
59 def build_q(token):
60 return build_q_object(field_name, phrases.get(token, token), use_regex, whole_words)
61
62 def parse_expression(expr):
63 expr = expr.strip()
64
65 if '(' in expr:
66 paren_start = expr.rfind('(')
67 paren_end = expr.find(')', paren_start)
68 if paren_end == -1:
69 return Q()
70
71 group_q = parse_expression(expr[paren_start + 1:paren_end])
72
73 before_str = expr[:paren_start].rstrip()
74 after_str = expr[paren_end + 1:].lstrip()
75
76 before_op = '&'
77 if before_str.upper().endswith(' AND'):
78 before_str = before_str[:-4].rstrip()
79 elif before_str.upper().endswith(' OR'):
80 before_str = before_str[:-3].rstrip()
81 before_op = '|'
82
83 after_op = '&'
84 after_upper = after_str.upper()
85 if after_upper.startswith('AND '):
86 after_str = after_str[4:].lstrip()
87 elif after_upper.startswith('OR '):
88 after_str = after_str[3:].lstrip()
89 after_op = '|'
90
91 result = group_q
92 if before_str:

Callers 3

postMethod · 0.90
searchMethod · 0.85

Calls 2

extract_quotedFunction · 0.85
parse_expressionFunction · 0.85

Tested by

no test coverage detected