Skip to content

Commit 3322988

Browse files
committed
when strict check is false we convert the passed number into string
1 parent 6b4beb6 commit 3322988

File tree

5 files changed

+77
-9
lines changed

5 files changed

+77
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# DeepDiff Change log
22

3+
- v5-4-0: adding strict_checking for numbers in DeepSearch
34
- v5-3-0: add support for regular expressions in DeepSearch
45
- v5-2-3: Retaining the order of multiple dictionary items added via Delta. Fixed the typo with yml files in deep cli. Fixing Grep RecursionError where using non UTF-8 character. Allowing kwargs to be passed to to_json method.
56
- v5-2-2: Fixed Delta serialization when None type is present.

deepdiff/search.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ class DeepSearch(dict):
4343
If False, the value of the item can be a part of the value of the object or its children
4444
4545
use_regexp: Boolean, default = False
46-
strict_checking: Boolean, default = False
47-
If True, it won't check the type of the object to match, so '1234' will match
48-
the int 1234.
46+
47+
strict_checking: Boolean, default = True
48+
If True, it will check the type of the object to match, so when searching for '1234',
49+
it will NOT match the int 1234. Currently this only affects the numeric values searching.
4950
5051
**Returns**
5152
@@ -114,8 +115,13 @@ def __init__(self,
114115
matched_values=self.__set_or_dict(),
115116
unprocessed=[])
116117
self.use_regexp = use_regexp
118+
if not strict_checking and isinstance(item, numbers):
119+
item = str(item)
117120
if self.use_regexp:
118-
item = re.compile(item)
121+
try:
122+
item = re.compile(item)
123+
except TypeError as e:
124+
raise TypeError(f"The passed item of {item} is not usable for regex: {e}") from None
119125
self.strict_checking = strict_checking
120126

121127
# Cases where user wants to match exact string item
@@ -272,9 +278,13 @@ def __search_str(self, obj, item, parent):
272278

273279
def __search_numbers(self, obj, item, parent):
274280
if (
275-
item == obj
276-
or (not self.strict_checking and item == str(obj))
277-
or (not self.strict_checking and self.use_regexp and item.search(str(obj)))
281+
item == obj or (
282+
not self.strict_checking and (
283+
item == str(obj) or (
284+
self.use_regexp and item.search(str(obj))
285+
)
286+
)
287+
)
278288
):
279289
self.__report(report_key='matched_values', key=parent, value=obj)
280290

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Changelog
55

66
DeepDiff Changelog
77

8+
- v5-4-0: adding strict_checking for numbers in DeepSearch
89
- v5-3-0: add support for regular expressions in DeepSearch
910
- v5-2-3: Retaining the order of multiple dictionary items added via Delta. Fixed the typo with yml files in deep cli. Fixing Grep RecursionError where using non UTF-8 character. Allowing kwargs to be passed to to_json method.
1011
- v5-2-2: Fixed Delta serialization when None type is present.

docs/search_doc.rst

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
1-
grep is a more user friendly interface for DeepSearch. It takes exactly the same arguments as DeepSearch.
2-
And it works just like grep in linux shell!
1+
grep is a more user friendly interface for DeepSearch. It takes exactly the same arguments as DeepSearch except that you pipe the object into it instead of passing it as a parameter.
2+
3+
It works just like grep in linux shell!
4+
5+
**Parameters**
6+
7+
item : The item to search for
8+
9+
verbose_level : int >= 0, default = 1.
10+
Verbose level one shows the paths of found items.
11+
Verbose level 2 shows the path and value of the found items.
12+
13+
exclude_paths: list, default = None.
14+
List of paths to exclude from the report.
15+
16+
exclude_types: list, default = None.
17+
List of object types to exclude from the report.
18+
19+
case_sensitive: Boolean, default = False
20+
21+
match_string: Boolean, default = False
22+
If True, the value of the object or its children have to exactly match the item.
23+
If False, the value of the item can be a part of the value of the object or its children
24+
25+
use_regexp: Boolean, default = False
26+
27+
strict_checking: Boolean, default = True
28+
If True, it will check the type of the object to match, so when searching for '1234',
29+
it will NOT match the int 1234. Currently this only affects the numeric values searching.
30+
331

432
**Examples**
533

@@ -28,3 +56,16 @@ You can also use regular expressions
2856
>>> ds = obj | grep("some.*", use_regexp=True)
2957
{ 'matched_paths': ["root[1]['someone']", "root[1]['somewhere']"],
3058
'matched_values': ['root[0]', "root[1]['long']"]}
59+
60+
61+
Change strict_checking to False to match numbers in strings and vice versa:
62+
>>> obj = {"long": "somewhere", "num": 1123456, 0: 0, "somewhere": "around"}
63+
>>> item = "1234"
64+
>>> result = {"matched_values": {"root['num']"}}
65+
>>> ds = obj | grep(item, verbose_level=1, use_regexp=True)
66+
>>> pprint(ds)
67+
{}
68+
>>>
69+
>>> ds = obj | grep(item, verbose_level=1, use_regexp=True, strict_checking=False)
70+
>>> pprint(ds)
71+
{'matched_values': ["root['num']"]}

tests/test_search.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,21 @@ def test_regex_in_int_in_dictionary_returns_partial_match(self):
452452
ds = DeepSearch(obj, item, verbose_level=1, use_regexp=True, strict_checking=False)
453453
assert ds == result
454454

455+
def test_int_cant_become_regex(self):
456+
obj = {"long": "somewhere", "num": "1123456", 0: 0, "somewhere": "around"}
457+
item = CustomClass(a=10)
458+
with pytest.raises(TypeError) as exp:
459+
DeepSearch(obj, item, verbose_level=1, use_regexp=True, strict_checking=False)
460+
assert str(exp.value).startswith("The passed item of (10, None) is not usable for regex")
461+
462+
def test_searching_for_int_in_dictionary_when_strict_false(self):
463+
obj = {"long": "somewhere", "num": "1234", 0: 0, "somewhere": "around"}
464+
item = 1234
465+
result = {"matched_values": {"root['num']"}}
466+
ds = DeepSearch(obj, item, verbose_level=1, strict_checking=False)
467+
assert ds == result
468+
469+
455470
class TestGrep:
456471

457472
def test_grep_dict(self):

0 commit comments

Comments
 (0)