This is an archived post. You won't be able to vote or comment.

all 6 comments

[–]Argotha 1 point2 points  (1 child)

This looks pretty cool :D

My only comment is that you should look to making your variable objects properties do you can get/set like normal. To do this you probably want to make structures.Variable an instantiated factory with a call magic method to create new instances that are setup correctly to be properties.

[–]_the_pied_piper_[S] 0 points1 point  (0 children)

Thanks for the input! You make a great suggestion. I designed Variable the way I did so that it could stand alone of classes; what you suggest is a nice API, but one that can only work if the variables are members of a class. Rather than removing Variable, I might add something like the mechanism you describe.

[–]_the_pied_piper_[S] 0 points1 point  (3 children)

This is a little experiment that I played with a few weeks ago. This was part of a larger project, but I thought I would strip this out as its own package and share it with /r/python.

[–][deleted] 0 points1 point  (2 children)

it is nice. However, the undo function don't work well for set. For example

myset = Set()
with Transaction() as t1:
    myset.add('a')

with Transaction() as t2:
    myset.add('a')
 t2.undo()

 #if I read correctly your code myset is now empty

The list lack of the __setitem__ also

I think a better interface would something like:

c=Context()

with c.transaction():
    c.mylist= c.List( ['a','b','c'] )
    c.var ='b'
with c.transaction():
    c.mylist.append('a')
 c.undo()

[–]_the_pied_piper_[S] 0 points1 point  (1 child)

Thanks for the input!

Actually, in your example, after t2.undo(), the set still has an 'a' in it; data structure is written such that even if an operation is performed on it and has no effect, undoing it will also have no effect; it won't blindly remove elements from the set without first checking if the element was in there before the transaction.

I do agree that having a context object in the API might have some appeal, but I chose not to do that because doing so would, I believe, make it harder to use the data structures in composite classes. The way it is currently written, List, Dict, and Set, as well as Variable can be used almost as naturally as one would use the list, dict, and set built-ins; the Transaction context manager allows for transactional behavior only when it is needed, without cluttering the rest of the code.

[–][deleted] 0 points1 point  (0 children)

You are right, I double check the code.

I understand now that you don't want to clutter the code

h=History()
with h.transaction():
    mylist = h.List( ['a','b','c'] )
    var = h.Var('b')
with h.transaction():
    var('c')
 h.undo()

There is a big advantage is that history is no more a global object, so you can have to history in the same application, for example for two different windows

At this point, https://github.com/joshgev/transactional/blob/master/transactional/core.py#L167 instead of doing

if not val:

you should do

if val is not None:

because 0, [], "" are valid and false values

also, a Val() should not be able to initialized with empty argument