API Documentation
reem
- class reem.RedisInterface(host: str = 'localhost', marshallers=[<reem.marshalling.NumpyMarshaller object>], *args, **kwargs)
Low level class for interfacing with Redis. Notably, stores the set of marshallers used for accessing Numpy and other user data.
Variable args and keyword arguments are passed to a
redis.Redis()
constructor.- hostname
the hostname of the Redis server (default localhost)
- Type
str
- marshallers
the list of marshallers used for decoding Python objects like Numpy arrays.
- Type
List[Marshaller]
- client
the ReJSON client
- Type
redis.Redis
- client_no_decode
the ReJSON client used for communicating with Redis without decoding JSON results.
- Type
redis.Redis
- client_copy()
- class reem.KeyValueStore(interface: Union[str, reem.connection.RedisInterface, reem.connection.KeyValueStore] = 'localhost', *args, **kwargs)
Dictionary Like object used for get/set paradigm
The
KeyValueStore
object is one that users will frequently use. It keepsReader
andWriter
objects for each key that the user has read or written to. It does not actually handle the getting and setting of data but producesKeyAccessor
objects that assist with path construction and call the reader and writer’s write and read methods.When constructing this class, users can pass through
*args
and**kwargs
that will be forwarded to theRedisInterface
and eventually to theRedis
client. This allows users to set things like socket timeouts. See https://redis.readthedocs.io/en/latest/connections.html for a full list of options.- interface
Defines the connection to Redis this reader will use. If a str, then a RedisInterface will be created and connected to automatically.
- Type
str, RedisInterface, or KeyValueStore
- get(path: str) Any
Reads a path in the form ‘key.element1.element2’ from the redis server. If the path doesn’t exist, an error is raised.
Marginally faster than nested accessors.
- set(path: str, value: Any) None
Sets a value in a path in the form ‘key.element1.element2’ from the redis server. If any elements along the path, except for the last key, do not exist, an error is raised.
value
must be a JSON-serializable object.Marginally faster than nested accessors.
- track_schema_changes(track: bool, keys=None) None
Performance optimization for skipping schema update checks
Stop checking for schema updates when setting data. Use ONLY if your data’s schema is static and you are really trying to eke out every bit of optimization.
- Parameters
track (bool) – True/False indicating if the keys’ schema should be tracked
keys (List[str]) – List of keys to track. If None, all present and future keys are tracked according to
track
Returns: None
- class reem.TolerantKeyValueStore(interface: Union[str, reem.connection.RedisInterface, reem.connection.KeyValueStore] = 'localhost', refreshRate: float = 0, *args, **kwargs)
TolerantKeyValueStore acts almost like a normal KeyValueStore, except for the following advantages when using the
var()
,set()
, andget()
methods:More tolerant of uninitialized keys and will fill in empty dicts as needed.
Can accept paths in the form of string paths
['key1','key2']
or period- separated keys'key1.key2'
Note
Does not accept path strings that include integer array indices, yet. To access arrays, you will need to pass in arrays, e.g.
['key1','key2',3]
There are also some performance enhancements when using
var()
:If you are accessing a sub-key many times in success to obtain its sub-objects, storing a
var()
once and accessing its sub-keys is much faster because it will cache the object and avoid making many calls to the server.If you are accessing a sub-key of a large object, use
var(path_to_item)
rather thanvar(key1)[key2][...]
. The latter will retrieve the whole object referenced by key1.You may play around with the cache refresh time with the second argument to
var()
or with the attributedefaultVarRefreshRate
. If you have a slow item that only updates occasionally, e.g., by user input, set a larger refresh, e.g.var(path,2)
will make at most one query to the server per 2 seconds.
- var(path: Union[str, list], refreshRate: Optional[float] = None) reem.convenience.TolerantKVSVar
Given a path (period-separated str or list of str), returns a
TolerantKVSVar
object that accesses the key using get()/set().All parent keys in path will be created as empty dictionaries if they don’t exist.
If refreshRate!=0, values will be cached, only refreshing after refreshRate seconds elapse. This minimizes server traffic.
- get(path: Union[str, list]) Any
Given a path (period-separated str or list of str), returns a JSON object or numpy array at path by recursively descending into self.
- set(path: Union[str, list], value: Any)
Given a path (period-separated str or list of str), sets a value in the state server. The item must be json-encodable or a numpy array.
If you are accessing a path with multiple subkeys that don’t exist, the subkeys will be added.
- class reem.PublishSpace(interface: Union[str, reem.connection.RedisInterface, reem.connection.KeyValueStore] = 'localhost', *args, **kwargs)
Convenience class for publishing
This class keeps track of
PublishWriter
objects for each key the user has published on.
- class reem.CallbackSubscriber(channel: str, interface: Union[str, reem.connection.RedisInterface], callback_function: Callable, kwargs)
A Subscriber that calls a user-defined callback every time a publisher sends a message. You can also access the most up-to-date value using value() or [key].
The callback function is of the form f(channel,message,**kwargs) and is called every time it receives a message published on channel_name*
- call_user_function(channel, message)
Wrapper callback function (wrapping user function) for this class to work with a RawSubscriber object Fits required interface for a ChannelSubscriber callback function :param channel: channel published to :param message: message that was published :return: None :rtype: None
- class reem.SilentSubscriber(channel: str, interface: Union[str, reem.connection.RedisInterface])
A Subscriber that reads updates into a local dict, and users access the most up-to-date values using value() or [key].
- update_local_copy(channel, message)
Update the local copy of the data stored under this channel name in redis.
- Parameters
channel – the name of the channel that was published.
message – message published on that channel
Returns: None
- listen() None
Makes this subscriber start listening
Returns: None
- value()
Get data stored at root
Where as the reader can do
server["foo"].read()
with if server is aKeyValueStore
, accessing the root value of a subscriber is not as easy. This method retrieves all data stored underneath a top level key.Returns: all data stored underneath a top level Redis key.
reem.connection
- class reem.connection.RedisInterface(host: str = 'localhost', marshallers=[<reem.marshalling.NumpyMarshaller object>], *args, **kwargs)
Low level class for interfacing with Redis. Notably, stores the set of marshallers used for accessing Numpy and other user data.
Variable args and keyword arguments are passed to a
redis.Redis()
constructor.- hostname
the hostname of the Redis server (default localhost)
- Type
str
- marshallers
the list of marshallers used for decoding Python objects like Numpy arrays.
- Type
List[Marshaller]
- client
the ReJSON client
- Type
redis.Redis
- client_no_decode
the ReJSON client used for communicating with Redis without decoding JSON results.
- Type
redis.Redis
- client_copy()
- class reem.connection.KeyValueStore(interface: Union[str, reem.connection.RedisInterface, reem.connection.KeyValueStore] = 'localhost', *args, **kwargs)
Dictionary Like object used for get/set paradigm
The
KeyValueStore
object is one that users will frequently use. It keepsReader
andWriter
objects for each key that the user has read or written to. It does not actually handle the getting and setting of data but producesKeyAccessor
objects that assist with path construction and call the reader and writer’s write and read methods.When constructing this class, users can pass through
*args
and**kwargs
that will be forwarded to theRedisInterface
and eventually to theRedis
client. This allows users to set things like socket timeouts. See https://redis.readthedocs.io/en/latest/connections.html for a full list of options.- interface
Defines the connection to Redis this reader will use. If a str, then a RedisInterface will be created and connected to automatically.
- Type
str, RedisInterface, or KeyValueStore
- get(path: str) Any
Reads a path in the form ‘key.element1.element2’ from the redis server. If the path doesn’t exist, an error is raised.
Marginally faster than nested accessors.
- set(path: str, value: Any) None
Sets a value in a path in the form ‘key.element1.element2’ from the redis server. If any elements along the path, except for the last key, do not exist, an error is raised.
value
must be a JSON-serializable object.Marginally faster than nested accessors.
- track_schema_changes(track: bool, keys=None) None
Performance optimization for skipping schema update checks
Stop checking for schema updates when setting data. Use ONLY if your data’s schema is static and you are really trying to eke out every bit of optimization.
- Parameters
track (bool) – True/False indicating if the keys’ schema should be tracked
keys (List[str]) – List of keys to track. If None, all present and future keys are tracked according to
track
Returns: None
- class reem.connection.PublishSpace(interface: Union[str, reem.connection.RedisInterface, reem.connection.KeyValueStore] = 'localhost', *args, **kwargs)
Convenience class for publishing
This class keeps track of
PublishWriter
objects for each key the user has published on.
- class reem.connection.RawSubscriber(channel_name, interface, callback_function, kwargs)
A Subscriber that calls a callback function of the form f(channel,message,**kwargs) every time it receives a message published on channel_name*.
- listen()
- class reem.connection.SilentSubscriber(channel: str, interface: Union[str, reem.connection.RedisInterface])
A Subscriber that reads updates into a local dict, and users access the most up-to-date values using value() or [key].
- update_local_copy(channel, message)
Update the local copy of the data stored under this channel name in redis.
- Parameters
channel – the name of the channel that was published.
message – message published on that channel
Returns: None
- listen() None
Makes this subscriber start listening
Returns: None
- value()
Get data stored at root
Where as the reader can do
server["foo"].read()
with if server is aKeyValueStore
, accessing the root value of a subscriber is not as easy. This method retrieves all data stored underneath a top level key.Returns: all data stored underneath a top level Redis key.
- class reem.connection.CallbackSubscriber(channel: str, interface: Union[str, reem.connection.RedisInterface], callback_function: Callable, kwargs)
A Subscriber that calls a user-defined callback every time a publisher sends a message. You can also access the most up-to-date value using value() or [key].
The callback function is of the form f(channel,message,**kwargs) and is called every time it receives a message published on channel_name*
- call_user_function(channel, message)
Wrapper callback function (wrapping user function) for this class to work with a RawSubscriber object Fits required interface for a ChannelSubscriber callback function :param channel: channel published to :param message: message that was published :return: None :rtype: None
- class reem.connection.Writer(top_key_name: str, interface: reem.connection.RedisInterface)
Responsible for setting data inside Redis
The Writer class is an internal class that is used for all data sent to Redis (not including pub/sub messages). Each key that will have nested data below requires a new instantiation of Writer
- top_key_name
The name of the Redis key under which JSON data will be stored. To Redis, this will become a ReJSON key name. It is also used to generate the Redis key name that marshallers use to store non JSON data.
- Type
str
- interface
Defines the connection to Redis this writer will use
- Type
- send_to_redis(set_path, set_value)
Execute equivalent of
JSON.SET self.top_key_name <set_path> <set_value>
From the user’s perspective, it executes
JSON.SET self.top_key_name <set_path> <set_value>
except thatset_value
can be json-incompatible. In such a case, it determines what non-serializable types are inside set_value, stores the serializable data as a JSON, and stores the non-serializable data usingself.interface
’s marshallers.- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
- Returns
None
- delete_from_redis(del_path: str)
Execute equivalent of
JSON.DEL self.top_key_name <set_path>
- Parameters
del_path (str) – path underneath JSON key to delete
- Returns
None
- class reem.connection.Reader(top_key_name, interface)
Responsible for getting data from Redis
The Reader class is an internal class that is used for all read from Redis (not including pub/sub messages). Each key that will have nested data below requires a new instantiation of Reader
- top_key_name
The name of the Redis key under which JSON data is stored
- Type
str
- interface
Defines the connection to Redis this reader will use
- Type
- read_from_redis(read_path)
Read specified path from Redis
This is the only public method of the Reader class. It will retrieve the data stored at a specified path from Redis. At a high level, it reads data stored with ReJSON and inserts non-JSON compatible data at appropriate paths using the metadata associated with this key.
- Parameters
read_path (str) – path the user wants to read
Returns: data stored at value in Redis
- update_metadata()
Update the local copy of metadata if a relevant path has been updated.
The metadata listener is a redis client subscribed to key-space notifications. If a relevant path is updated, this Reader’s
pull_metadata
flag will be turned on. Ifpull_metadata
isTrue
, then the reader will fetch metadata from the Redis server.Returns: None
- queue_reads(read_path)
Queue reads in a pipeline
Queue all redis queries necessary to read data at path into the appropriate redis pipeline. First, queue decoded pipeline with the ReJSON query Next, queue all the special path reads with the non-decoded pipeline and marshallers
- Parameters
read_path – path user wants to read
Returns: None
- build_dictionary(read_path)
Execute pipelines and consolidate data into a dictionary
- Parameters
read_path – path user wants to read
Returns: The data stored at
read_path
in Redis
- pull_special_path(read_path)
Directly pull a non-JSON path
If the user specified path is not in JSON, this will retrieve the data directly without going through ReJSON.
- Parameters
read_path – path user wants to read
Returns:
- class reem.connection.PublishWriter(top_key_name, interface)
Identical to Writer, but publishes a message when it writes a value.
- send_to_redis(set_path, set_value)
PublishWriter equivalent of Writer
send_to_redis
This is an equivalent function to
Writer
’ssend_to_redis
method but also publishes a message indicating what channel has been updated.- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
Returns: None
- delete_from_redis(del_path)
Execute equivalent of
JSON.DEL self.top_key_name <set_path>
- Parameters
del_path (str) – path underneath JSON key to delete
- Returns
None
reem.accessors
- class reem.accessors.KeyAccessor(parent, writer, reader, initial_path=[])
Main class for accessing sub-keys of a KeyValueStore.
- get(key: str, default_value: Optional[Any] = None) Any
Similar to dict’s get() method, returns a default value if the key doesn’t exist.
Essentially equivalent to ``` try:
value = self[key].read()
- except:
value = default_value
- read() Any
Actually read the value referred to by this accessor.
- write(value: Any) None
Writes value to the path referred to by this accessor.
- type() str
Returns the type of the object
- append(rhs: Any) None
Appends a value to an array
Type checking is not performed, so the user should know what they’re doing.
- class reem.accessors.WriteOnlyKeyAccessor(*args, **kwargs)
- read()
Actually read the value referred to by this accessor.
- append(rhs)
Appends a value to an array
Type checking is not performed, so the user should know what they’re doing.
- class reem.accessors.ActiveSubscriberKeyAccessor(*args, **kwargs)
- write()
Writes value to the path referred to by this accessor.
- append(rhs)
Appends a value to an array
Type checking is not performed, so the user should know what they’re doing.
- read() Any
Actually read the value referred to by this accessor.
- class reem.accessors.ChannelListener(client, channel_name, callback_function, kwargs)
- 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.
reem.convenience
- class reem.convenience.TolerantKeyValueStore(interface: Union[str, reem.connection.RedisInterface, reem.connection.KeyValueStore] = 'localhost', refreshRate: float = 0, *args, **kwargs)
TolerantKeyValueStore acts almost like a normal KeyValueStore, except for the following advantages when using the
var()
,set()
, andget()
methods:More tolerant of uninitialized keys and will fill in empty dicts as needed.
Can accept paths in the form of string paths
['key1','key2']
or period- separated keys'key1.key2'
Note
Does not accept path strings that include integer array indices, yet. To access arrays, you will need to pass in arrays, e.g.
['key1','key2',3]
There are also some performance enhancements when using
var()
:If you are accessing a sub-key many times in success to obtain its sub-objects, storing a
var()
once and accessing its sub-keys is much faster because it will cache the object and avoid making many calls to the server.If you are accessing a sub-key of a large object, use
var(path_to_item)
rather thanvar(key1)[key2][...]
. The latter will retrieve the whole object referenced by key1.You may play around with the cache refresh time with the second argument to
var()
or with the attributedefaultVarRefreshRate
. If you have a slow item that only updates occasionally, e.g., by user input, set a larger refresh, e.g.var(path,2)
will make at most one query to the server per 2 seconds.
- var(path: Union[str, list], refreshRate: Optional[float] = None) reem.convenience.TolerantKVSVar
Given a path (period-separated str or list of str), returns a
TolerantKVSVar
object that accesses the key using get()/set().All parent keys in path will be created as empty dictionaries if they don’t exist.
If refreshRate!=0, values will be cached, only refreshing after refreshRate seconds elapse. This minimizes server traffic.
- get(path: Union[str, list]) Any
Given a path (period-separated str or list of str), returns a JSON object or numpy array at path by recursively descending into self.
- set(path: Union[str, list], value: Any)
Given a path (period-separated str or list of str), sets a value in the state server. The item must be json-encodable or a numpy array.
If you are accessing a path with multiple subkeys that don’t exist, the subkeys will be added.
- class reem.convenience.TolerantKVSVar(server: reem.convenience.TolerantKeyValueStore, path: Union[str, list], refreshRate: float = 0)
An accessor for a TolerantKeyValueStore. Can be more convenient than accessing the server via
server[key].read() / write()
because it will create parent keys from a period-separated path, and can be more efficient on reads due to caching and pre-creation of path strings.Supports operators [], del [], type(), len(), +=, -=, *=, /=, and append().
- get()
Reads the value at the given key from the state server
- set(value)
Sets the value at the given key into the state server.
- type()
- append(rhs)
- class reem.convenience.TolerantKVSVarSubkey(root: reem.convenience.TolerantKVSVar, parentnode, key: str)
Accessor for sub-keys of TolerantKVSVar’s. Respects cache, and refreshes the cache of the original object referenced by var().
Performs copy-on-write semantics.
Supports operators [], del [], type(), len(), +=, -=, *=, /=, and append().
- get()
- set(value)
- type()
- append(rhs)
reem.marshalling
- class reem.marshalling.SpecialDatatypeMarshaller
Abstract base class for marshallers that convert Python objects to/from ReJSON commands.
- abstract check_fit(value)
Determine if this marshaller will handle
value
This method returns true if
value
is data that this marshaller is supposed to handle. If this marshaller handled all numpy arrays, it would check ifvalue
’s type is a numpy array.- Parameters
value – object to check
Returns: True if marshaller will handle
value
- abstract write(key, value, client) None
Write
value
to Redis at the specifiedkey
usingclient
Given a Redis client, execute any number of needed commands to store the
value
in Redis. You are required to use the key given for REEM to find it. If you must store multiple pieces of information, use a Redis Hash which acts like a one level dictionary.- Parameters
key (str) – The Redis key name this marshaller must store data under
value – The value to write into Redis
client – A Redis Client
Returns: None
- abstract read(key, client)
Retrieve necessary information from Redis
Given a Redis client, execute ONE command to retrieve all the information you need to rebuild the data that was stored in
write
from Redis. This method should execute the command that allows you to retrieve all data stored under key.- Parameters
key (str) – a keyname that contains data stored by
write
client –
Returns: None
- abstract delete(key, client)
Delete information from redis at the specified
key
usingclient
.Given a Redis client, execute any number of commands to retrieve all the information you need to delete all of the data stored under
key
- Parameters
key (str) – a keyname that contains data stored by
write
client –
Returns: None
- abstract interpret_read(responses)
Translate Redis data into a local object
Redis will reply to you with something according to what read command you executed in
read
. This method takes whatever Redis replied with and turns it into an object identical to what was initially passed towrite
as value.- Parameters
responses – Redis’s reply data based on
read
method
Returns: An object identical to what was initially written to Redis.
- abstract get_label()
Return a unique string identifier
This method should return a string that uniquely identifies this marshaller. REEM will use it to determine what marshaller to use to decode data that is already stored in Redis.
- Returns
the string identifier
- Return type
str
- class reem.marshalling.NumpyMarshaller
A marshaller for Numpy arrays.
- check_fit(value)
Determine if this marshaller will handle
value
This method returns true if
value
is data that this marshaller is supposed to handle. If this marshaller handled all numpy arrays, it would check ifvalue
’s type is a numpy array.- Parameters
value – object to check
Returns: True if marshaller will handle
value
- get_label()
Return a unique string identifier
This method should return a string that uniquely identifies this marshaller. REEM will use it to determine what marshaller to use to decode data that is already stored in Redis.
- Returns
the string identifier
- Return type
str
- write(key, value, client)
Write
value
to Redis at the specifiedkey
usingclient
Given a Redis client, execute any number of needed commands to store the
value
in Redis. You are required to use the key given for REEM to find it. If you must store multiple pieces of information, use a Redis Hash which acts like a one level dictionary.- Parameters
key (str) – The Redis key name this marshaller must store data under
value – The value to write into Redis
client –
Returns: None
- delete(key, client)
Delete information from redis at the specified
key
usingclient
.Given a Redis client, execute any number of commands to retrieve all the information you need to delete all of the data stored under
key
- Parameters
key (str) – a keyname that contains data stored by
write
client –
Returns: None
- read(key, client)
Retrieve necessary information from Redis
Given a Redis client, execute ONE command to retrieve all the information you need to rebuild the data that was stored in
write
from Redis. This method should execute the command that allows you to retrieve all data stored under key.- Parameters
key (str) – a keyname that contains data stored by
write
client –
Returns: None
- interpret_read(responses)
Translate Redis data into a local object
Redis will reply to you with something according to what read command you executed in
read
. This method takes whatever Redis replied with and turns it into an object identical to what was initially passed towrite
as value.- Parameters
responses – Redis’s reply data based on
read
method
Returns: An object identical to what was initially written to Redis.