stefankoegl / python-json-patch

Applying JSON Patches in Python
https://python-json-patch.readthedocs.org/
BSD 3-Clause "New" or "Revised" License
434 stars 94 forks source link

Bug - Typerror: unsupported operand type(s) for -=: 'unicode' and 'int' on make_patch() #119

Closed RyanSept closed 2 years ago

RyanSept commented 3 years ago

Version: 1.28 Python version: 2.7.17

Description I run into an error TypeError: unsupported operand type(s) for -=: 'unicode' and 'int' when diffing these two objects. This happens on Python 2 but on Python 3, it works without error.

td1 = {'id': '123',
 'data': [{'ext': {'1': ['lettuce', 'cabbage', 'bok choy', 'broccoli'],
    '10_1576156603109': [],
    '2': ['apple'],
    '3': ['ibex'],
    '4': ['gerenuk', 'duiker'],
    '5': [],
    '6': [],
    '7_1572034204585': [],
    '8_1572034252560': ['thompson', 'gravie', 'mango', 'coconut']},
   'schema_id': 'id999',
   'updated_at': '2021-01-04T14:00:39+00:00'},
  {'ext': {'description': '', 'title': ''},
   'schema_id': 'id001',
   'updated_at': '2021-01-04T14:00:38+00:00'}],
 'updated_at': '2021-01-04T14:00:33+00:00'}

 td2 = {'id': '123',
 'data': [{'ext': {'10': 'yes',
    '12': '',
    '16_1598876845275': [],
    '7': ['pecan'],
    '9': ['almond']},
   'schema_id': 'id765',
   'updated_at': '2021-01-04T14:00:39+00:00'},
  {'ext': {'1': ['lettuce', 'cabbage', 'bok choy', 'broccoli'],
    '10_1576156603109': [],
    '2': ['apple'],
    '3': ['ibex'],
    '4': ['gerenuk', 'duiker'],
    '5': [],
    '6': [],
    '7_1572034204585': [],
    '8_1572034252560': ['thompson', 'gravie', 'mango', 'coconut']},
   'schema_id': 'id999',
   'updated_at': '2021-01-04T14:00:39+00:00'},
  {'ext': {'description': '', 'title': ''},
   'schema_id': 'id001',
   'updated_at': '2021-01-04T14:00:38+00:00'}],
 'updated_at': '2021-01-04T14:00:33+00:00'}

Steps to reproduce

import jsonpatch
jsonpatch.make_patch(td1, td2)

Stack trace

/lib/python2.7/site-packages/jsonpatch.pyc in make_patch(src, dst, pointer_cls)
    173     """
    174
--> 175     return JsonPatch.from_diff(src, dst, pointer_cls=pointer_cls)
    176
    177

/lib/python2.7/site-packages/jsonpatch.pyc in from_diff(cls, src, dst, optimization, dumps, pointer_cls)
    637         json_dumper = dumps or cls.json_dumper
    638         builder = DiffBuilder(json_dumper, pointer_cls=pointer_cls)
--> 639         builder._compare_values('', None, src, dst)
    640         ops = list(builder.execute())
    641         return cls(ops, pointer_cls=pointer_cls)

/lib/python2.7/site-packages/jsonpatch.pyc in _compare_values(self, path, key, src, dst)
    873         if isinstance(src, MutableMapping) and \
    874                 isinstance(dst, MutableMapping):
--> 875             self._compare_dicts(_path_join(path, key), src, dst)
    876
    877         elif isinstance(src, MutableSequence) and \

/lib/python2.7/site-packages/jsonpatch.pyc in _compare_dicts(self, path, src, dst)
    840
    841         for key in src_keys & dst_keys:
--> 842             self._compare_values(path, key, src[key], dst[key])
    843
    844     def _compare_lists(self, path, src, dst):

/lib/python2.7/site-packages/jsonpatch.pyc in _compare_values(self, path, key, src, dst)
    877         elif isinstance(src, MutableSequence) and \
    878                 isinstance(dst, MutableSequence):
--> 879             self._compare_lists(_path_join(path, key), src, dst)
    880
    881         # To ensure we catch changes to JSON, we can't rely on a simple

/lib/python2.7/site-packages/jsonpatch.pyc in _compare_lists(self, path, src, dst)
    854                 elif isinstance(old, MutableMapping) and \
    855                     isinstance(new, MutableMapping):
--> 856                     self._compare_dicts(_path_join(path, key), old, new)
    857
    858                 elif isinstance(old, MutableSequence) and \

/lib/python2.7/site-packages/jsonpatch.pyc in _compare_dicts(self, path, src, dst)
    840
    841         for key in src_keys & dst_keys:
--> 842             self._compare_values(path, key, src[key], dst[key])
    843
    844     def _compare_lists(self, path, src, dst):

/lib/python2.7/site-packages/jsonpatch.pyc in _compare_values(self, path, key, src, dst)
    873         if isinstance(src, MutableMapping) and \
    874                 isinstance(dst, MutableMapping):
--> 875             self._compare_dicts(_path_join(path, key), src, dst)
    876
    877         elif isinstance(src, MutableSequence) and \

/lib/python2.7/site-packages/jsonpatch.pyc in _compare_dicts(self, path, src, dst)
    834
    835         for key in removed_keys:
--> 836             self._item_removed(path, str(key), src[key])
    837
    838         for key in added_keys:

/lib/python2.7/site-packages/jsonpatch.pyc in _item_removed(self, path, key, item)
    803             if type(op.key) == int:
    804                 for v in self.iter_from(index):
--> 805                     op.key = v._on_undo_add(op.path, op.key)
    806
    807             self.remove(index)

/lib/python2.7/site-packages/jsonpatch.pyc in _on_undo_add(self, path, key)
    434         if self.path == path:
    435             if self.key > key:
--> 436                 self.key -= 1
    437             else:
    438                 key += 1

TypeError: unsupported operand type(s) for -=: 'unicode' and 'int'
RyanSept commented 3 years ago

Hi @stefankoegl. I'd wish to put in a fix for this and I'd appreciate your guidance on where I should start