Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
tinysync
-
I know this is not very Pythonic, as it makes things more implicit than explicit, but I wanted to see how far I could push this approach of making things "just happen" without the developer always having to worry about the boilerplate.
So, lots of "magic" around simple dict/list data structures:
Magic 1 - React to changes
from tinysync import track data = { 'a': [1, 2], 'b': [3, 4] } data = track(data, change_callback=my_func)
With this,
my_func
is called with change details whenever you make any changes to the data (which can be a combo of dicts, lists and sets).Not sure how terribly useful this is as a stand-alone capability - maybe for updating the UI every time the data changes?
Magic 2 - Persist data
data = track(data, 'config.yaml')
With this, all further changes to the data are saved as YAML into a file called 'config.yaml'. If there already is a file,
data
is initialized from its contents.This I have found quite useful as a no-fuss persistence of configurations and similar. There is also support for other file formats and DBMs.
Magic 3 - Thread safety
with data: data['b'][1] = data['a'][0]
If you have multiple threads and need to make complex changes to the data, using the structure itself as a context manager locks it, making other threads wait.
Magic 4 - Versions
from tinysync import track, handler data = track({}, history=True) h = handler(data).history data['a'] = 5 data['a'] = [1, 2] len(h) # 2 h.undo() h.active # 1 data['a'] # 5 h.redo() # 0 data['a'] # [1, 2]
Since we react to changes, it is natural to store deltas and play them backwards and forwards. This could be a fit for some kind of a configuration editor, I think.
Magic 5 - Transactions
from tinysync import track, atomic data = track(data, 'config.yaml') with atomic(data): del data['option2'] data['option1'] = True
With the
atomic
context manager, all the changes are applied, or none. In the example above, ifdel
throws an error, data is not left in an inconsistent state, and nothing is written to file. Also, if you use versions, all the changes within the context manager are treated as one revision.Dangerous Magic 6 - Dot access
from tinysync import track, dot_on dot_on() data = track({ 'options': { 'option1': 'value', 'option2': 'value } }) print(data.options.option1)
For those who like this option, despite the additional potential confusion to the readers of the code.
Implementation of all of the above relies heavily on the dictdiffer package, and is not much concerned with performance. Code on github is quite beta.
-
-
-
@mikael I had understood, not as usual 😀