vinegar.utils.smart_dict

Provides a dictionary that has a smart get method.

The get method of SmartLookupDict is implemented in a way that makes it easy to look for values in nested dictionaries.

For example, take a dictionary with the following content:

{'key1': {'key2': {'key3': 'value'}}}

In order to get the nested value, one would ordinarily have to use one of the two following expressions:

value = regular_dict['key1']['key2']['key3']
value = regular_dict.get('key1').get('key2').get('key3')

This is particularly bothersome if one cannot be sure that the nested value even exists. In order to use a default value if one of the keys is missing, one could use nested calls to get with default values:

value = regular_dict.get(
    'key1', {}).get('key2', {}).get('key3', 'default value')

An alternative would be catching the KeyError:

try:
    value = regular_dict['key1']['key2']['key3']
catch KeyError:
    value = "default value"

Both alternatives are not very user friendly, in particular if used from a template language where a try...catch construct might not be available.

The smart dictionaries make such use cases either by enabling the user to get a nested value in a single call to get:

value = smart_dict.get('key1:key2:key3', 'default value')

By default the colon (:) is used as the key separator, but this can be changed by specifying the sep argument:

value = smart_dict.get('key1_key2_key3', 'default value', sep='_')

In addition to handling nested dicts, the smart-lookup dict can also handle nested lists. For example, consider a dictionary with the following content:

{‘key1’: [‘a’, ‘b’, {‘nested_key’: 123}]}

The nested values can be looked up in the following way:

smart_dict.get(‘key1:0’) smart_dict.get(‘key1:2:nested_key’)

In addition to the get method, the setdefault method is overriden, so that it automatically inserts nested dictionaries if needed. Please note that setdefault can handle traversing lists, but it cannot handle inserting a new item into a list.

The implementation of get provided by the smart lookup dictionaries also differs from the one for regular dictionaries in that it do not use a default value of None by default. Instead, it raises a KeyError if the key is not found and no default value is provided.

class vinegar.utils.smart_dict.SmartLookupDict

Dict that allows easy lookup and setting of nested values.

get(key, *args, **kwargs)

Return the value for key.

If key is not in the dictionary and default is given, return default. If default is not given raise a KeyError.

The key can be a nested key into nested dictionaries inside this dictionary. The key is split using the sep (default :) and each component is used as the key on one level of nested dictionaries, the first component being used at the top level.

Parameters:
  • key – key for which the value shall be looked up. This can be a nested key into nested dictionaries. sep is used to separate components of the key.

  • default – default value to be returned if this dictionary (or one of the nested dictionaries) does not contain key. If not specified, a KeyError is raised instead.

  • sep – separator separating components in key. The default is :.

Returns:

value for key or default if specified and key is not found.

setdefault(key, default=None, sep=':', dict_type=<class 'dict'>)

Return the value for key inserting and returning default if key does not exist yet.

The key can be a nested key into nested dictionaries inside this dictionary. The key is split using the sep (default :) and each component is used as the key on one level of nested dictionaries, the first component being used at the top level.

If one of the key components except the last key component is not found, a new dictionary of type dict_type is inserted automatically.

Parameters:
  • key – key for which the value shall be looked up. This can be a nested key into nested dictionaries. sep is used to separate components of the key.

  • default – default value to be inserted and returned if this dictionary (or one of the nested dictionaries) does not contain key.

  • dict_type – the type of dictionary that is created when a new dictionary has to be inserted. The default is dict.

Returns:

value for key or default if key is not found.