You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
J. Fernando Sánchez eaddd89e8c minor bug fixes 1 year ago
tests First commit 3 years ago
tsih minor bug fixes 1 year ago
.gitignore First commit 3 years ago
LICENSE First commit 3 years ago First commit 3 years ago First commit 3 years ago
requirements.txt First commit 3 years ago
setup.cfg First commit 3 years ago First commit 3 years ago
test-requirements.txt First commit 3 years ago

TSIH - A dict with a HISTory

tsih.Dict is a type of UserDict that allows versioning, backed up by a sqlite3 database.

  • Transparent operation
  • Only changes (deltas) are stored.
  • Forward-filling of values. A value is reused in future versions, unless it changes.
  • Auto-versioning option (off by default), to produce a new version every time a value change happens.
  • Ability to store related entries as separate dictionaries. Each tsih.Dict has a dict_name that is used in the database to identify the dictionary.
  • Tuple-based indexing. Get and set values by dict_name, version and key.

Usage and examples

tsih.Dict objects can be used just like regular dictionaries:

>>> from tsih import Dict
>>> a = Dict()
>>> a['test'] = True
>>> a
{'test': True}
>>> a.get('missing', 5)
>>> a['missing']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'missing'

But at any point, new versions can be produced:

>>> a.version
>>> a['start'] = 'now'
>>> a
{'test': True, 'start': 'now'}
>>> a.version = 1
>>> a['start'] = 'one version ago'
>>> a
{'test': True, 'start': 'one version ago'}

Previous values can be accessed using tuple keys, i.e., (version, key):

>>> a[(0, 'start')]
>>> a[(1, 'start')]
'one version ago'

Each version only "records" changes, but later versions (even if they don't exist yet) inherit unchanged values from the previous ones:

>>> a[(5, 'start')]  
'one version ago'
>>> a.version = 5
>>> # Until the value is changed
>>> a['start'] = '4 versions ago' 
>>> a[(5, 'start')]
'4 versions ago'

You can access every state of the Dict using None in place of the version and/or the key. In that case, we will get an iterator, which we can turn into a list explicitly or with the .value method.

For example, here we get all the changes to the start key:

>>> a[(None, 'start')].value() # 
[(0.0, 'now'), (1.0, 'one version ago'), (5.0, '4 versions ago')]

Similarly, to get the keys and values at a specific version:

>>> list(a[(0, None)])
[('start', 'now'), ('test', True)]

Or, we can combine both to get the keys and values at every version:

>>> a[(None, None)].value()
[(0.0, 'start', 'now'), (1.0, 'start', 'one version ago'), (5.0, 'start', '4 versions ago'), (0.0, 'test', True), (1.0, 'test', True), (5.0, 'test', True)]

Use cases

Tsih was originally part of the Soil Agent-Based Social Simulation framework, where both the environment and the agents need to keep track of state (i.e., attribute) changes.