|
1 | 1 | import json |
| 2 | +import numbers |
2 | 3 | import re |
3 | 4 |
|
4 | 5 | import numpy as np |
@@ -190,6 +191,37 @@ def or_operands(search_struct): |
190 | 191 | return operands |
191 | 192 |
|
192 | 193 |
|
| 194 | +def _has_member(value, member): |
| 195 | + """Is *member* a member of *value*, for field_search's 'hasmember'? |
| 196 | +
|
| 197 | + Text is a member of text that is the whole value or an item of its |
| 198 | + comma-separated list (white space after a comma, and before one, is |
| 199 | + ignored); anything is a member of a list that holds an equal element; a |
| 200 | + number is a member of an equal number. Text is never a member of a |
| 201 | + number, nor a number of text. This is what DID-matlab's fieldsearch and |
| 202 | + its SQL search match (DID-matlab#236). |
| 203 | + """ |
| 204 | + |
| 205 | + def is_number(x): |
| 206 | + return isinstance(x, numbers.Real) and not isinstance(x, str) |
| 207 | + |
| 208 | + if isinstance(value, np.ndarray): |
| 209 | + value = value.tolist() |
| 210 | + if isinstance(member, str): |
| 211 | + if isinstance(value, str): |
| 212 | + pattern = r"(^|,\s*)" + re.escape(member) + r"\s*(,|$)" |
| 213 | + return re.search(pattern, value) is not None |
| 214 | + if isinstance(value, (list, tuple)): |
| 215 | + return any(isinstance(v, str) and v == member for v in value) |
| 216 | + return False |
| 217 | + if is_number(member): |
| 218 | + if is_number(value): |
| 219 | + return value == member |
| 220 | + if isinstance(value, (list, tuple)): |
| 221 | + return any(is_number(v) and v == member for v in value) |
| 222 | + return False |
| 223 | + |
| 224 | + |
193 | 225 | def field_search(a, search_struct): |
194 | 226 | """ |
195 | 227 | Searches a dictionary to determine if it matches a search structure. |
@@ -260,10 +292,7 @@ def field_search(a, search_struct): |
260 | 292 | b = eq_len(np.array(value).shape, param1) |
261 | 293 | elif op_lower == "hasmember": |
262 | 294 | if is_there: |
263 | | - try: |
264 | | - b = param1 in value |
265 | | - except TypeError: |
266 | | - pass |
| 295 | + b = _has_member(value, param1) |
267 | 296 | elif op_lower == "hasfield": |
268 | 297 | b = is_there |
269 | 298 | elif op_lower == "partial_struct": |
|
0 commit comments