satella.coding.structures.dictionaries package

Submodules

satella.coding.structures.dictionaries.cache_dict module

class satella.coding.structures.dictionaries.cache_dict.CacheDict(stale_interval, expiration_interval, value_getter, value_getter_executor=None, cache_failures_interval=None, time_getter=<built-in function monotonic>, default_value_factory=None)

Bases: Mapping[K, V]

A dictionary that you can use as a cache.

The idea is that you might want to cache some values, and they might be stale after some interval (after which they will need to be refreshed), and they will expire after some other interval (after which a call to get them will block until they are refreshed), but stale values are safe to serve from memory, while expired values are not and the dict will need to block until they are available.

If a stale value is read, a refresh is scheduled in the background for it. If an expired value is read, it will block until the result is available. Else, the value is served straight from fast memory.

Note that value_getter raising KeyError is not cached, so don’t use this cache for situations where misses are frequent.

Parameters:
  • stale_interval (Union[float, int, str]) – time in seconds after which an entry will be stale, ie. it will be served from cache, but a task will be launched in background to refresh it. Note that this will accept time-like strings eg. 23m.

  • expiration_interval (Union[float, int, str]) – time in seconds after which an entry will be ejected from dict, and further calls to get it will block until the entry is available. Note that this will accept time-like strings eg. 23m.

  • value_getter (Callable[[K], V]) – a callable that accepts a key, and returns a value for given entry. If value_getter raises KeyError, then given entry will be evicted from the cache

  • value_getter_executor (Optional[Executor]) – an executor to execute the value_getter function in background. If None is passed, a ThreadPoolExecutor will be used with max_workers of 4.

  • cache_failures_interval (Optional[Union[float, int, str]]) – if any other than None is defined, this is the timeout for which failed lookups will be cached. By default they won’t be cached at all. Note that this will accept time-like strings eg. 23m.

  • time_getter (Callable[[], float]) – a routine used to get current time in seconds

  • default_value_factory (Optional[Callable[[], V]]) – if given, this is the callable that will return values that will be given to user instead of throwing KeyError. If not given (default), KeyError will be thrown

feed(key, value, timestamp=None)

Feed this data into the cache

Parameters:
  • key (K) –

  • value (V) –

  • timestamp (Optional[float]) –

get_value_block(key)

Get a value using value_getter. Block until it’s available. Store it into the cache.

Raises:

KeyError – the value is not present at all

Parameters:

key (K) –

Return type:

V

has_info_about(key)

Is provided key cached, or failure about it is cached?

Parameters:

key (K) –

Return type:

bool

invalidate(key)

Remove all information about given key from the cache

Syntactic sugar for:

>>> try:
>>>   del self[key]
>>> except KeyError:
>>>   pass
Parameters:

key (K) –

Return type:

None

schedule_a_fetch(key)

Schedule a value refresh for given key

Parameters:

key (K) – key to schedule the refresh for

Returns:

future that was queued to ask for given key

Return type:

Future

class satella.coding.structures.dictionaries.cache_dict.LRUCacheDict(*args, max_size=100, **kwargs)

Bases: CacheDict[K, V]

A dictionary that you can use as a cache with a maximum size, items evicted by LRU policy.

Parameters:

max_size (int) – maximum size

evict()
feed(key, value, timestamp=None)

Feed this data into the cache

Parameters:
  • key (K) –

  • value (V) –

  • timestamp (Optional[float]) –

get_value_block(key)

Get a value using value_getter. Block until it’s available. Store it into the cache.

Raises:

KeyError – the value is not present at all

Parameters:

key (K) –

Return type:

V

invalidate(key)

Remove all information about given key from the cache

Syntactic sugar for:

>>> try:
>>>   del self[key]
>>> except KeyError:
>>>   pass
Parameters:

key (K) –

Return type:

None

make_room()

Assure that there’s place for at least one element

Return type:

None

satella.coding.structures.dictionaries.counting module

class satella.coding.structures.dictionaries.counting.CountingDict(set_to_count=())

Bases: object

A dictionary to quickly count the amount of elements in a set

Parameters:

set_to_count (Sequence) – a sequence, whose elements should be counted. The elements should support being keys in a dictionary.

clear()
count(elem, pieces=1)

Add an instance of elem to the set

Parameters:
  • elem – instance to add

  • pieces (int) – amount to add

Return type:

None

dct
items()
keys()
values()

satella.coding.structures.dictionaries.default module

class satella.coding.structures.dictionaries.default.DefaultDict

Bases: defaultdict

A collections.defaultdict that does not store in itself empty values that it generates

satella.coding.structures.dictionaries.dict_object module

class satella.coding.structures.dictionaries.dict_object.DictObject(*args, **kwargs)

Bases: dict

A dictionary wrapper that can be accessed by attributes.

Note that it still remains a completely valid dictionary!

You can use keys different than strings, but they will be inaccessible as attributes, and you will have to do subscription to get them.

Eg:

>>> a = DictObject({'test': 5})
>>> self.assertEqual(a.test, 5)
>>> self.assertEqual(a['test'], 5)
is_valid_schema(schema=None, **kwarg_schema)

Check if this dictionary conforms to particular schema.

Schema is either a Descriptor, or a JSON-based schema. See satella.configuration.schema for details. Schema can be passed as well using kwargs. Note that the schema argument will be ignored if kwargs are passed.

Parameters:

schema (Optional[Union[Descriptor, Dict]]) – schema to verify against

Returns:

whether is conformant

Return type:

bool

satella.coding.structures.dictionaries.dict_object.apply_dict_object(v)

Apply DictObject() to every dict inside v.

This assumes that the only things that will be touched will be nested dicts and lists.

If you pass a non-dict and a non-list, they will be returned as is.

Parameters:

v (Union[Any, Dict]) –

Return type:

Union[DictObject, Any]

satella.coding.structures.dictionaries.expiring module

class satella.coding.structures.dictionaries.expiring.Cleanupable

Bases: object

abstract cleanup()
Return type:

None

class satella.coding.structures.dictionaries.expiring.ExpiringEntryDict(expiration_timeout, *args, time_getter=<built-in function monotonic>, external_cleanup=False, **kwargs)

Bases: Monitor, MutableMapping[K, V], Cleanupable

A dictionary whose entries expire automatically after a predefined period of time.

Note that cleanup is invoked only when iterating over the dicts, or automatically if you specify external_cleanup to be True each approximately 5 seconds.

Note that it’s preferential to satella.coding.concurrent.Monitor.acquire() it if you’re using an external cleanup thread, because the dict may mutate at any time.

Parameters:
  • expiration_timeout (float) – number of seconds after which entries will expire

  • time_getter (Callable[[], float]) – a callable/0 that returns the current timestamp

  • external_cleanup (bool) – whether to spawn a single thread that will clean up the dictionary. The thread is spawned once per program, and no additional threads are spawned for next dictionaries.

All args and kwargs will be passed to a dict, which will be promptly added to this dictionary.

You need to invoke this at your constructor You can also use it to release locks of other objects.

cleanup()

Remove entries that are later than given time

Return type:

None

get_timestamp(key)

Return the timestamp at which given key was inserted in the dict

Raises:

KeyError – key not found in the dictionary

Parameters:

key (K) –

Return type:

float

class satella.coding.structures.dictionaries.expiring.ExpiringEntryDictThread

Bases: Thread, Monitor

A background thread providing maintenance for expiring entry dicts and self-cleaning default dicts

This constructor should always be called with keyword arguments. Arguments are:

group should be None; reserved for future extension when a ThreadGroup class is implemented.

target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.

name is the thread name. By default, a unique name is constructed of the form “Thread-N” where N is a small decimal number.

args is a list or tuple of arguments for the target invocation. Defaults to ().

kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.

If a subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.

add_dict(ed)
Parameters:

ed (Cleanupable) –

Return type:

None

cleanup()
Return type:

None

run()

Method representing the thread’s activity.

You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.

Return type:

None

start()

Start the thread’s activity.

It must be called at most once per thread object. It arranges for the object’s run() method to be invoked in a separate thread of control.

This method will raise a RuntimeError if called more than once on the same thread object.

Return type:

None

class satella.coding.structures.dictionaries.expiring.SelfCleaningDefaultDict(default_factory, background_maintenance=True, *args, **kwargs)

Bases: Monitor, MutableMapping[K, V], Cleanupable

A defaultdict with the property that if it detects that a value is equal to it’s default value, it will automatically remove it from the dict.

Please note that this will spawn a cleanup thread in the background, one per program. The thread is shared between satella.coding.structures.SelfCleaningDefaultDict and satella.coding.structures.ExpiringEntryDict

It is preferable to satella.coding.concurrent.Monitor.acquire() it before iterating, since it is cleaned up both by __iter__ and by an external worker thread, so it’s important to acquire it, because it can mutate in an undefined way.

Note that if you access a key which does not exist, and background_maintenance is False, a default value will be created and inserted into the dictionary. This is the only time that the dictionary will hold values that are equal to default.

Parameters:
  • default_factory (Callable[[], V]) – a callable/0 that will return an object if it doesn’t already exist

  • background_maintenance (bool) – whether to spawn a background thread. This is required if dictionary values can change their value between inserts.

All args and kwargs will be passed to a dict, which will be promptly added to this dictionary.

You need to invoke this at your constructor You can also use it to release locks of other objects.

cleanup()
Return type:

None

satella.coding.structures.dictionaries.objects module

class satella.coding.structures.dictionaries.objects.DictionaryView(master_dict, *rest_of_dicts, propagate_deletes=True, assign_to_same_dict=True)

Bases: MutableMapping[K, V]

A view on a multiple dictionaries. If key isn’t found in the first dictionary, it is looked up in another. Use like:

>>> dv = DictionaryView({1:2, 3:4}, {4: 5, 6: 7})
>>> assert dv[4] == 5
>>> del dv[1]
>>> assertRaises(KeyError, lambda: dv.__delitem__(1))

Deprecated since version 2.14.22: Use ChainMap instead.

Parameters:
  • master_dict (tp.Dict[K, V]) – First dictionary to look up. Entries made via __setitem__ will be put here.

  • rest_of_dicts (tp.Dict[K, V]) – Remaining dictionaries

  • propagate_deletes (bool) – Whether to delete given key from the first dictionary that it is found. Otherwise it will be only deleted from the master_dict. Also, if this is set to False, on deletion, if the key isn’t found in master dictionary, deletion will KeyError.

  • assign_to_same_dict (bool) – whether updates done by __setitem__ should be written to the dictionary that contains that key. If not, all updates will be stored in master_dict. If this is True, updates made to keys that are not in this dictionary will go to master_dict.

assign_to_same_dict
dictionaries
master_dict
propagate_deletes
class satella.coding.structures.dictionaries.objects.DirtyDict(*args, **kwargs)

Bases: MutableMapping[K, V]

A dictionary that has also a flag called .dirty that sets to True if the dictionary has been changed since that flag was last cleared.

Setting the dict with the value that it already has doesn’t count as dirtying it. Note that such changes will not be registered in the dict!

All arguments and kwargs will be passed to dict’s constructor.

clear_dirty()

Clears the dirty flag

Return type:

None

copy_and_clear_dirty()

Returns a copy of this data and sets dirty to False

Returns:

a plain, normal Python dictionary is returned

Return type:

Dict[K, V]

swap_and_clear_dirty()

Returns this data, clears self and sets dirty to False

After this is called, this dict will be considered empty.

Returns:

a plain, normal Python dictionary is returned

Return type:

Dict[K, V]

class satella.coding.structures.dictionaries.objects.KeyAwareDefaultDict(factory_function, *args, **kwargs)

Bases: MutableMapping[K, V]

A defaultdict whose factory function accepts the key to provide a default value for the key

Parameters:

factory_function (tp.Callable[[K], V]) – a callable that accepts a single argument, a key, for which it is to provide a default value

class satella.coding.structures.dictionaries.objects.TwoWayDictionary(data=None, _is_reverse=False)

Bases: MutableMapping[K, V]

A dictionary that keeps also a reverse_data mapping, allowing to look up keys by values.

Not thread-safe.

Example usage:

>>> twd = TwoWayDictionary()
>>> twd[2] = 3
>>> self.assertEqual(twd.reverse[3], 2)

When you’re done using a given TwoWayDictionary, please call .done(). This will make it easier for the GC to collect the dictionaries.

You can also use the context manager to make the TwoWayDictionary clean up itself, eg.

>>> with TwoWayDictionary() as twd:
>>>     ...
>>> # at this point twd is .done()
Parameters:
  • data – data to generate the dict from

  • _is_reverse (bool) –

Raises:

ValueError – on being given data from which it is impossible to construct a reverse mapping (ie. same value appears at least twice)

data
done()

Called when the user is done using given TwoWayDictionary.

Internally this will break the reference cycle, and enable Python GC to collect the objects.

Return type:

None

property reverse: MutableMapping[V, K]

Return a reverse mapping. Reverse mapping is updated as soon as an operation is done.

reverse_data

satella.coding.structures.dictionaries.writeback_cache module

class satella.coding.structures.dictionaries.writeback_cache.ExclusiveWritebackCache(write_method, read_method, delete_method=None, executor=None, no_concurrent_executors=None, store_key_errors=True)

Bases: Generic[K, V]

A dictionary implementing an exclusive write-back cache. By exclusive it is understood that only this object will be modifying the storage.

Parameters:
  • write_method (Callable[[K, V], None]) – a blocking callable (key, value) that writes the value to underlying storage.

  • read_method (Callable[[K], V]) – a blocking callable (key) -> value that retrieves the piece of data from the cache, or throws a KeyError to signal that the value does not exist

  • delete_method (Optional[Callable[[K], None]]) – optional, a blocking callable (key) that erases the data from the storage. If not given, it will be a TypeError to delete the data from this storage

  • executor (Optional[Executor]) – an executor to execute the calls with. If None (default) is given, a ThreadPoolExecutor with 4 workers will be created

  • no_concurrent_executors (Optional[int]) – number of concurrent jobs that the executor is able to handle. This is used by sync()

  • store_key_errors (bool) – whether to remember KeyErrors raised by read_method

cache
cache_lock
delete_method
executor
get_queue_length()

Return current amount of entries waiting for writeback

Return type:

int

in_cache
no_concurrent_executors
operations
read_method
store_key_errors
sync(timeout=None)

Wait until current tasks are complete.

Parameters:

timeout (Optional[float]) – timeout to wait. None means wait indefinitely.

Raises:

WouldWaitMore – if timeout has expired

Return type:

None

write_method

Module contents

class satella.coding.structures.dictionaries.CacheDict(stale_interval, expiration_interval, value_getter, value_getter_executor=None, cache_failures_interval=None, time_getter=<built-in function monotonic>, default_value_factory=None)

Bases: Mapping[K, V]

A dictionary that you can use as a cache.

The idea is that you might want to cache some values, and they might be stale after some interval (after which they will need to be refreshed), and they will expire after some other interval (after which a call to get them will block until they are refreshed), but stale values are safe to serve from memory, while expired values are not and the dict will need to block until they are available.

If a stale value is read, a refresh is scheduled in the background for it. If an expired value is read, it will block until the result is available. Else, the value is served straight from fast memory.

Note that value_getter raising KeyError is not cached, so don’t use this cache for situations where misses are frequent.

Parameters:
  • stale_interval (Union[float, int, str]) – time in seconds after which an entry will be stale, ie. it will be served from cache, but a task will be launched in background to refresh it. Note that this will accept time-like strings eg. 23m.

  • expiration_interval (Union[float, int, str]) – time in seconds after which an entry will be ejected from dict, and further calls to get it will block until the entry is available. Note that this will accept time-like strings eg. 23m.

  • value_getter (Callable[[K], V]) – a callable that accepts a key, and returns a value for given entry. If value_getter raises KeyError, then given entry will be evicted from the cache

  • value_getter_executor (Optional[Executor]) – an executor to execute the value_getter function in background. If None is passed, a ThreadPoolExecutor will be used with max_workers of 4.

  • cache_failures_interval (Optional[Union[float, int, str]]) – if any other than None is defined, this is the timeout for which failed lookups will be cached. By default they won’t be cached at all. Note that this will accept time-like strings eg. 23m.

  • time_getter (Callable[[], float]) – a routine used to get current time in seconds

  • default_value_factory (Optional[Callable[[], V]]) – if given, this is the callable that will return values that will be given to user instead of throwing KeyError. If not given (default), KeyError will be thrown

feed(key, value, timestamp=None)

Feed this data into the cache

Parameters:
  • key (K) –

  • value (V) –

  • timestamp (Optional[float]) –

get_value_block(key)

Get a value using value_getter. Block until it’s available. Store it into the cache.

Raises:

KeyError – the value is not present at all

Parameters:

key (K) –

Return type:

V

has_info_about(key)

Is provided key cached, or failure about it is cached?

Parameters:

key (K) –

Return type:

bool

invalidate(key)

Remove all information about given key from the cache

Syntactic sugar for:

>>> try:
>>>   del self[key]
>>> except KeyError:
>>>   pass
Parameters:

key (K) –

Return type:

None

schedule_a_fetch(key)

Schedule a value refresh for given key

Parameters:

key (K) – key to schedule the refresh for

Returns:

future that was queued to ask for given key

Return type:

Future

class satella.coding.structures.dictionaries.CountingDict(set_to_count=())

Bases: object

A dictionary to quickly count the amount of elements in a set

Parameters:

set_to_count (Sequence) – a sequence, whose elements should be counted. The elements should support being keys in a dictionary.

clear()
count(elem, pieces=1)

Add an instance of elem to the set

Parameters:
  • elem – instance to add

  • pieces (int) – amount to add

Return type:

None

dct
items()
keys()
values()
class satella.coding.structures.dictionaries.DefaultDict

Bases: defaultdict

A collections.defaultdict that does not store in itself empty values that it generates

class satella.coding.structures.dictionaries.DictObject(*args, **kwargs)

Bases: dict

A dictionary wrapper that can be accessed by attributes.

Note that it still remains a completely valid dictionary!

You can use keys different than strings, but they will be inaccessible as attributes, and you will have to do subscription to get them.

Eg:

>>> a = DictObject({'test': 5})
>>> self.assertEqual(a.test, 5)
>>> self.assertEqual(a['test'], 5)
is_valid_schema(schema=None, **kwarg_schema)

Check if this dictionary conforms to particular schema.

Schema is either a Descriptor, or a JSON-based schema. See satella.configuration.schema for details. Schema can be passed as well using kwargs. Note that the schema argument will be ignored if kwargs are passed.

Parameters:

schema (Optional[Union[Descriptor, Dict]]) – schema to verify against

Returns:

whether is conformant

Return type:

bool

class satella.coding.structures.dictionaries.DictionaryView(master_dict, *rest_of_dicts, propagate_deletes=True, assign_to_same_dict=True)

Bases: MutableMapping[K, V]

A view on a multiple dictionaries. If key isn’t found in the first dictionary, it is looked up in another. Use like:

>>> dv = DictionaryView({1:2, 3:4}, {4: 5, 6: 7})
>>> assert dv[4] == 5
>>> del dv[1]
>>> assertRaises(KeyError, lambda: dv.__delitem__(1))

Deprecated since version 2.14.22: Use ChainMap instead.

Parameters:
  • master_dict (tp.Dict[K, V]) – First dictionary to look up. Entries made via __setitem__ will be put here.

  • rest_of_dicts (tp.Dict[K, V]) – Remaining dictionaries

  • propagate_deletes (bool) – Whether to delete given key from the first dictionary that it is found. Otherwise it will be only deleted from the master_dict. Also, if this is set to False, on deletion, if the key isn’t found in master dictionary, deletion will KeyError.

  • assign_to_same_dict (bool) – whether updates done by __setitem__ should be written to the dictionary that contains that key. If not, all updates will be stored in master_dict. If this is True, updates made to keys that are not in this dictionary will go to master_dict.

assign_to_same_dict
dictionaries
master_dict
propagate_deletes
class satella.coding.structures.dictionaries.DirtyDict(*args, **kwargs)

Bases: MutableMapping[K, V]

A dictionary that has also a flag called .dirty that sets to True if the dictionary has been changed since that flag was last cleared.

Setting the dict with the value that it already has doesn’t count as dirtying it. Note that such changes will not be registered in the dict!

All arguments and kwargs will be passed to dict’s constructor.

clear_dirty()

Clears the dirty flag

Return type:

None

copy_and_clear_dirty()

Returns a copy of this data and sets dirty to False

Returns:

a plain, normal Python dictionary is returned

Return type:

Dict[K, V]

swap_and_clear_dirty()

Returns this data, clears self and sets dirty to False

After this is called, this dict will be considered empty.

Returns:

a plain, normal Python dictionary is returned

Return type:

Dict[K, V]

class satella.coding.structures.dictionaries.ExclusiveWritebackCache(write_method, read_method, delete_method=None, executor=None, no_concurrent_executors=None, store_key_errors=True)

Bases: Generic[K, V]

A dictionary implementing an exclusive write-back cache. By exclusive it is understood that only this object will be modifying the storage.

Parameters:
  • write_method (Callable[[K, V], None]) – a blocking callable (key, value) that writes the value to underlying storage.

  • read_method (Callable[[K], V]) – a blocking callable (key) -> value that retrieves the piece of data from the cache, or throws a KeyError to signal that the value does not exist

  • delete_method (Optional[Callable[[K], None]]) – optional, a blocking callable (key) that erases the data from the storage. If not given, it will be a TypeError to delete the data from this storage

  • executor (Optional[Executor]) – an executor to execute the calls with. If None (default) is given, a ThreadPoolExecutor with 4 workers will be created

  • no_concurrent_executors (Optional[int]) – number of concurrent jobs that the executor is able to handle. This is used by sync()

  • store_key_errors (bool) – whether to remember KeyErrors raised by read_method

cache
cache_lock
delete_method
executor
get_queue_length()

Return current amount of entries waiting for writeback

Return type:

int

in_cache
no_concurrent_executors
operations
read_method
store_key_errors
sync(timeout=None)

Wait until current tasks are complete.

Parameters:

timeout (Optional[float]) – timeout to wait. None means wait indefinitely.

Raises:

WouldWaitMore – if timeout has expired

Return type:

None

write_method
class satella.coding.structures.dictionaries.ExpiringEntryDict(expiration_timeout, *args, time_getter=<built-in function monotonic>, external_cleanup=False, **kwargs)

Bases: Monitor, MutableMapping[K, V], Cleanupable

A dictionary whose entries expire automatically after a predefined period of time.

Note that cleanup is invoked only when iterating over the dicts, or automatically if you specify external_cleanup to be True each approximately 5 seconds.

Note that it’s preferential to satella.coding.concurrent.Monitor.acquire() it if you’re using an external cleanup thread, because the dict may mutate at any time.

Parameters:
  • expiration_timeout (float) – number of seconds after which entries will expire

  • time_getter (Callable[[], float]) – a callable/0 that returns the current timestamp

  • external_cleanup (bool) – whether to spawn a single thread that will clean up the dictionary. The thread is spawned once per program, and no additional threads are spawned for next dictionaries.

All args and kwargs will be passed to a dict, which will be promptly added to this dictionary.

You need to invoke this at your constructor You can also use it to release locks of other objects.

cleanup()

Remove entries that are later than given time

Return type:

None

get_timestamp(key)

Return the timestamp at which given key was inserted in the dict

Raises:

KeyError – key not found in the dictionary

Parameters:

key (K) –

Return type:

float

class satella.coding.structures.dictionaries.KeyAwareDefaultDict(factory_function, *args, **kwargs)

Bases: MutableMapping[K, V]

A defaultdict whose factory function accepts the key to provide a default value for the key

Parameters:

factory_function (tp.Callable[[K], V]) – a callable that accepts a single argument, a key, for which it is to provide a default value

class satella.coding.structures.dictionaries.LRUCacheDict(*args, max_size=100, **kwargs)

Bases: CacheDict[K, V]

A dictionary that you can use as a cache with a maximum size, items evicted by LRU policy.

Parameters:

max_size (int) – maximum size

evict()
feed(key, value, timestamp=None)

Feed this data into the cache

Parameters:
  • key (K) –

  • value (V) –

  • timestamp (Optional[float]) –

get_value_block(key)

Get a value using value_getter. Block until it’s available. Store it into the cache.

Raises:

KeyError – the value is not present at all

Parameters:

key (K) –

Return type:

V

invalidate(key)

Remove all information about given key from the cache

Syntactic sugar for:

>>> try:
>>>   del self[key]
>>> except KeyError:
>>>   pass
Parameters:

key (K) –

Return type:

None

make_room()

Assure that there’s place for at least one element

Return type:

None

class satella.coding.structures.dictionaries.SelfCleaningDefaultDict(default_factory, background_maintenance=True, *args, **kwargs)

Bases: Monitor, MutableMapping[K, V], Cleanupable

A defaultdict with the property that if it detects that a value is equal to it’s default value, it will automatically remove it from the dict.

Please note that this will spawn a cleanup thread in the background, one per program. The thread is shared between satella.coding.structures.SelfCleaningDefaultDict and satella.coding.structures.ExpiringEntryDict

It is preferable to satella.coding.concurrent.Monitor.acquire() it before iterating, since it is cleaned up both by __iter__ and by an external worker thread, so it’s important to acquire it, because it can mutate in an undefined way.

Note that if you access a key which does not exist, and background_maintenance is False, a default value will be created and inserted into the dictionary. This is the only time that the dictionary will hold values that are equal to default.

Parameters:
  • default_factory (Callable[[], V]) – a callable/0 that will return an object if it doesn’t already exist

  • background_maintenance (bool) – whether to spawn a background thread. This is required if dictionary values can change their value between inserts.

All args and kwargs will be passed to a dict, which will be promptly added to this dictionary.

You need to invoke this at your constructor You can also use it to release locks of other objects.

cleanup()
Return type:

None

class satella.coding.structures.dictionaries.TwoWayDictionary(data=None, _is_reverse=False)

Bases: MutableMapping[K, V]

A dictionary that keeps also a reverse_data mapping, allowing to look up keys by values.

Not thread-safe.

Example usage:

>>> twd = TwoWayDictionary()
>>> twd[2] = 3
>>> self.assertEqual(twd.reverse[3], 2)

When you’re done using a given TwoWayDictionary, please call .done(). This will make it easier for the GC to collect the dictionaries.

You can also use the context manager to make the TwoWayDictionary clean up itself, eg.

>>> with TwoWayDictionary() as twd:
>>>     ...
>>> # at this point twd is .done()
Parameters:
  • data – data to generate the dict from

  • _is_reverse (bool) –

Raises:

ValueError – on being given data from which it is impossible to construct a reverse mapping (ie. same value appears at least twice)

data
done()

Called when the user is done using given TwoWayDictionary.

Internally this will break the reference cycle, and enable Python GC to collect the objects.

Return type:

None

property reverse: MutableMapping[V, K]

Return a reverse mapping. Reverse mapping is updated as soon as an operation is done.

reverse_data
satella.coding.structures.dictionaries.apply_dict_object(v)

Apply DictObject() to every dict inside v.

This assumes that the only things that will be touched will be nested dicts and lists.

If you pass a non-dict and a non-list, they will be returned as is.

Parameters:

v (Union[Any, Dict]) –

Return type:

Union[DictObject, Any]