Skip to content

Instantly share code, notes, and snippets.

@johanste
Created January 23, 2020 03:20
Show Gist options
  • Save johanste/3ffb05d17f97b9dc8e417f8c7a87114d to your computer and use it in GitHub Desktop.
Save johanste/3ffb05d17f97b9dc8e417f8c7a87114d to your computer and use it in GitHub Desktop.
Example wrapping existing model type into something that can build json-patch (like) documents
class JsonPatchProxy:
def __init__(self, wrapped, *, root=None, selector=''):
self.__wrapped = wrapped
self.__root = root or self
self.__selector = selector
self.__operations = []
def __getattr__(self, name):
attr = getattr(self.__wrapped, name)
return JsonPatchProxy(
attr, root=self.__root, selector=f'{self.__selector}/{name}'
)
def __setattr__(self, name, value):
if name in ('_JsonPatchProxy__wrapped', '_JsonPatchProxy__root', '_JsonPatchProxy__operations', '_JsonPatchProxy__selector'):
return super().__setattr__(name, value)
self.__wrapped.__setattr__(name, value)
self.__root.__operations.append(('set', f'{self.__selector}/{name}', value))
def __getitem__(self, key):
attr = self.__wrapped.__getitem__(key)
return JsonPatchProxy(
attr, root = self.__root, selector=f'{self.__selector}[{key}]'
)
def __setitem__(self, key, value):
self.__wrapped.__setitem__(key, value)
self.__root.__operations.append(('insert', f'{self.__selector}[{key}]', value))
def uniqueserialize(self):
return self.__operations
def unwrap(self):
return self.__wrapped
class ExampleModel:
"""Just an example model. Just to test things
"""
def __init__(self, size, items, map):
self.size = size
self.items = items
self.map = map
m = JsonPatchProxy(ExampleModel(2, ['foo', 'bar'], dict(a='b', c='d', e=dict(f='g'))))
m.size = 17
m.items[1] = 'updated'
m.items[0] = 'another update...'
m.map['z'] = 'yeah!'
m.map['e']['hello'] = 'world'
print(m.uniqueserialize())
w = m.unwrap()
print(w.size, w.items, w.map)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment