Skip to content

Commit c2c6341

Browse files
[DAGE-122] refactored escape into BaseSearchEngine
1 parent f8f1f0a commit c2c6341

4 files changed

Lines changed: 39 additions & 35 deletions

File tree

rre-tools/src/rre_tools/shared/search_engines/search_engine_base.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,25 @@
99
NUMBER_OF_DOCS_EACH_FETCH = 100
1010

1111
class BaseSearchEngine(ABC):
12+
13+
SPECIAL_CHARS: set[str] = {'\\', '+', '-', '!', '(', ')', ':', '^', '[', ']', '"',
14+
'{', '}', '~', '*', '?', '|', '&', '/'}
15+
1216
def __init__(self, endpoint: HttpUrl):
1317
self.endpoint = HttpUrl(endpoint)
1418
self.QUERY_PLACEHOLDER = "$query"
1519
self.UNIQUE_KEY = 'id'
1620

21+
@staticmethod
22+
def escape(string: str) -> str:
23+
"""Escape special characters used in query syntax."""
24+
sb = []
25+
for c in string:
26+
if c in BaseSearchEngine.SPECIAL_CHARS:
27+
sb.append('\\')
28+
sb.append(c)
29+
return ''.join(sb)
30+
1731
def fetch_all(self, doc_fields: List[str]) -> Iterator[Document]:
1832
"""Extract all documents from search engine in batches.
1933

rre-tools/src/rre_tools/shared/search_engines/solr_search_engine.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ class SolrSearchEngine(BaseSearchEngine):
1919
"""
2020
Solr implementation to search into a given collection
2121
"""
22-
SPECIAL_CHARS: set[str] = {'\\', '+', '-', '!', '(', ')', ':', '^', '[', ']', '"',
23-
'{', '}', '~', '*', '?', '|', '&', '/'}
2422

2523
def __init__(self, endpoint: HttpUrl):
2624
super().__init__(endpoint)
@@ -29,21 +27,11 @@ def __init__(self, endpoint: HttpUrl):
2927
self.UNIQUE_KEY = requests.get(urljoin(self.endpoint.encoded_string(), 'schema/uniquekey')).json()['uniqueKey']
3028
log.debug(f"uniqueKey found: {self.UNIQUE_KEY}")
3129

32-
3330
@property
3431
def _fetch_all_payload(self) -> Dict[str, Any]:
3532
return {
3633
'q': '*:*',
3734
}
38-
@staticmethod
39-
def escape(string: str) -> str:
40-
"""Escape special characters used in query syntax."""
41-
sb = []
42-
for c in string:
43-
if c in SolrSearchEngine.SPECIAL_CHARS:
44-
sb.append('\\')
45-
sb.append(c)
46-
return ''.join(sb)
4735

4836
def _unify_fields(self, doc_fields: List[str]) -> str:
4937
fields = doc_fields if self.UNIQUE_KEY in doc_fields else doc_fields + [self.UNIQUE_KEY]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from rre_tools.shared.search_engines import BaseSearchEngine
2+
3+
4+
def test_escape_no_special_chars():
5+
assert BaseSearchEngine.escape("hello world") == "hello world"
6+
7+
def test_escape_basic_specials():
8+
assert BaseSearchEngine.escape("a+b") == "a\\+b"
9+
assert BaseSearchEngine.escape("field:value") == "field\\:value"
10+
assert BaseSearchEngine.escape("(test)") == "\\(test\\)"
11+
12+
def test_escape_multiple_specials():
13+
assert BaseSearchEngine.escape("a+b-(c*d)?") == "a\\+b\\-\\(c\\*d\\)\\?"
14+
assert BaseSearchEngine.escape("[range]~{json}") == "\\[range\\]\\~\\{json\\}"
15+
16+
def test_escape_with_backslash():
17+
assert BaseSearchEngine.escape("path\\to/file") == "path\\\\to\\/file"
18+
19+
def test_escape_quotes():
20+
assert BaseSearchEngine.escape('"phrase" AND title:book') == '\\"phrase\\" AND title\\:book'
21+
22+
def test_escape_all_special_chars():
23+
all_specials = r'\+-!():^[]"{}~*?|&/'
24+
expected = ''.join(['\\' + c for c in all_specials])
25+
assert BaseSearchEngine.escape(all_specials) == expected

rre-tools/tests/shared/search_engines/test_solr_search_engine.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -128,26 +128,3 @@ def test_solr_search_engine_bad_url__expects__raises_validation_error():
128128
with pytest.raises(ValidationError):
129129
_ = SolrSearchEngine("fake-NONurl")
130130

131-
132-
def test_escape_no_special_chars():
133-
assert SolrSearchEngine.escape("hello world") == "hello world"
134-
135-
def test_escape_basic_specials():
136-
assert SolrSearchEngine.escape("a+b") == "a\\+b"
137-
assert SolrSearchEngine.escape("field:value") == "field\\:value"
138-
assert SolrSearchEngine.escape("(test)") == "\\(test\\)"
139-
140-
def test_escape_multiple_specials():
141-
assert SolrSearchEngine.escape("a+b-(c*d)?") == "a\\+b\\-\\(c\\*d\\)\\?"
142-
assert SolrSearchEngine.escape("[range]~{json}") == "\\[range\\]\\~\\{json\\}"
143-
144-
def test_escape_with_backslash():
145-
assert SolrSearchEngine.escape("path\\to/file") == "path\\\\to\\/file"
146-
147-
def test_escape_quotes():
148-
assert SolrSearchEngine.escape('"phrase" AND title:book') == '\\"phrase\\" AND title\\:book'
149-
150-
def test_escape_all_special_chars():
151-
all_specials = r'\+-!():^[]"{}~*?|&/'
152-
expected = ''.join(['\\' + c for c in all_specials])
153-
assert SolrSearchEngine.escape(all_specials) == expected

0 commit comments

Comments
 (0)