cohml · GitHub

Overview

This PR contains a first pass at adding simple diff detection for precompiled regex. This fixes the bug referenced in #336. Questions/comments for @seperman in bold.

What this PR adds

deepdiff.DeepDiff now returns a diff if two re.Pattern objects consist of different patterns, flags, or groups.

>>> from deepdiff import DeepDiff
>>> from pprint import pp
>>> import re
>>> pattern_1 = re.compile('foo')
>>> pattern_2 = re.compile('foo')
>>> diff_12 = DeepDiff(pattern_1, pattern_2)
>>> pp(diff_12)
{}
>>> pattern_3 = re.compile('bar')
>>> diff_13 = DeepDiff(pattern_1, pattern_3)
>>> pp(diff_13)
{'values_changed': {'root': {'new_value': re.compile('bar'),
                             'old_value': re.compile('foo')}}}
>>> pattern_4 = re.compile('foo', flags=re.M)
>>> diff_14 = DeepDiff(pattern_1, pattern_4)
>>> pp(diff_14)
{'values_changed': {'root': {'new_value': re.compile('foo', re.MULTILINE),
                             'old_value': re.compile('foo')}}}

What this PR doesn't add

The diff doesn't provide any granular info on the specific difference(s), e.g., "the patterns + groups are the same and the flags are different".

I would like to implement this greater granularity, but perhaps you'd prefer to merge what this PR already does and just add that other stuff as a separate PR? Let me know.

Coverage report

---------- coverage: platform darwin, python 3.9.7-final-0 -----------
Name                        Stmts   Miss  Cover   Missing
---------------------------------------------------------
deepdiff/anyset.py             47      0   100%
deepdiff/base.py               34      0   100%
deepdiff/commands.py          116      3    97%   115, 118-119
deepdiff/deephash.py          326      2    99%   352-353
deepdiff/delta.py             359      2    99%   176-177
deepdiff/diff.py              834      3    99%   472, 793, 1680
deepdiff/distance.py          141      0   100%
deepdiff/helper.py            323      6    98%   93-94, 656-657, 665-668
deepdiff/lfucache.py          154      6    96%   18-19, 74, 107, 142, 218
deepdiff/model.py             408      1    99%   638
deepdiff/operator.py           28      1    96%   27
deepdiff/path.py              102      7    93%   74, 92, 122-126
deepdiff/search.py            148      0   100%
deepdiff/serialization.py     243     11    95%   20, 31, 373, 486-488, 523, 583-586
---------------------------------------------------------
TOTAL                        3263     42    99%

Note 1: _diff_booleans

One thing to note is that the precompiled regex detection relies on DeepDiff._diff_booleans. So now _diff_booleans acts more like a _diff_booleans_and_precompiled_regex.

At first I had created a dedicated DeepDiff._diff_precompiled_regex method, but then realized that it was identical to _diff_booleans which already exists. So I just reused _diff_booleans to avoid bloating the code base.

If you're okay with coopting _diff_booleans like this, we might as well collapse further and just do

if isinstance(level.t1, (booleans, Pattern)):
    self._diff_booleans(level, local_tree=local_tree)

Otherwise, I can recreate my original _diff_precompiled_regex method, or entertain anything else you'd propose.

Note 2: Delta

JFYI, I did not touch the code in deepdiff/delta.py, because it seems to already work as is.

>>> from deepdiff import Delta
>>> diff_bool = DeepDiff(True, False)
>>> Delta(diff_bool)
<Delta: {'values_changed': {'root': {'new_value': False}}}>
>>> Delta(diff_13)
<Delta: {'values_changed': {'root': {'new_value': re.compile('bar')}}}>

If anything looks amiss there, let me know and I will update the PR.

Read the original on github.com ↗