Skip to content

Adding condition values

Dmitry Romanov edited this page Mar 4, 2016 · 9 revisions

=== Basic types: int, float, bool, string ===

To store basic types one of the fields should be used:

  • ConditionType.STRING_FIELD
  • ConditionType.INT_FIELD
  • ConditionType.BOOL_FIELD
  • ConditionType.FLOAT_FIELD

Lets example it:

# Create RCDBProvider provider object and connect it to DB db = RCDBProvider("sqlite:///example.db")

Crete condition types

db.create_condition_type("int_val", ConditionType.INT_FIELD) db.create_condition_type("float_val", ConditionType.FLOAT_FIELD) db.create_condition_type("bool_val", ConditionType.BOOL_FIELD) db.create_condition_type("string_val", ConditionType.STRING_FIELD)

Add values to run 1

db.add_condition(1, "int_val", 1000) db.add_condition(1, "float_val", 2.5) db.add_condition(1, "bool_val", True) db.add_condition(1, "string_val", "test test")

Read values for run 1 and use them

condition = db.get_condition(1, "int_val") print condition.value

condition = db.get_condition(1, "float_val") print condition.value

condition = db.get_condition(1, "bool_val") print condition.value

condition = db.get_condition(1, "string_val") print condition.value

The output:

1000 2.5 True test test

=== Time information ===

A time information can be attached to any condition value. Standard python datetime is used for that: (Lets see the first example):

# Create condition type db.create_condition_type("my_val", ConditionType.INT_FIELD)

Add value and time information

db.add_condition(1, "my_val", 2000, datetime(2015, 10, 10, 15, 28, 12, 111111))

Get condition from database

condition = db.get_condition(1, "my_val")

print condition print "value =", condition.value print "name =", condition.name print "time =", condition.time

The output is:

value = 2000 name = my_val time = 2015-10-10 15:28:12.111111

If time is the only relevant information for a condition, then ConditionType.TIME_FIELD type can be used to create the condition type. In this case ''Condition.value'' field will have time information and time can be passed as value parameter of add_condition function:

db.create_condition_type("lunch_bell_rang", ConditionType.TIME_FIELD)

add value to run 1

time = datetime(2015, 9, 1, 14, 21, 01) db.add_condition(1, "lunch_bell_rang", time)

get from DB

val = self.db.get_condition(1, "lunch_bell_rang") print val.value print val.time

The output is:

2015-09-01 14:21:01 2015-09-01 14:21:01

Note that ''val.value'' and ''val.time'' are the same in this example.

=== Multiple values per run ===

To add many values of the same type, ''is_many_per_run'' parameter of ''create_condition_type'' function should be set to True. Then you are able to add many condition values per one run, but specifying time for each of them.

'''(!)''' if '''is_many_per_run=True''', then '''get_condition''' returns a list of Condition objects. Even if there is only one object selected.

Example

# Many condition values allowed for the run (is_many_per_run=True) # 1. If run has this condition, with the same value and actual_time the func. DOES NOTHING # 2. If run has this conditions but at different time, it adds this condition to DB

db.create_condition_type("multi", ConditionType.INT_FIELD)

time1 = datetime(2015,9,1,14,21,01, 222) time2 = datetime(2015,9,1,14,21,01, 333)

First addition to DB. Time is None

db.add_condition(1, "multi", 2222)

Ok. Value for time1 is added to DB

db.add_condition(1, "multi", 3333, time1) db.add_condition(1, "multi", 4444, time2)

results = db.get_condition(1, "multi")

We should get 3 values as:

0: value=2222; time=None

1: value=3333; time=time1

2: value=4444; time=time2

lets check it

print results values = [result.value for result in results] times = [result.time for result in results] print values print times

The output:

[, , ] [2222, 3333, 4444] [None, datetime(2015, 9, 1, 14, 21, 1, 222), datetime(2015, 9, 1, 14, 21, 1, 333)]

=== Arrays and dictionaries ===

Multiple values per run are '''NOT''' intended to store arrays of data.

Best way to store arrays and dictionaries is serializing them to JSON. Use ConditionType.JSON_FIELD for that. RCDB conditions API doesn't provide mechanisms of converting objects to JSON and from JSON. For arrays it is done easily by json module.

The example from https://docs.python.org/2/library/json.html python 2.7 documentation:

>>> import json >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) '["foo", {"bar": ["baz", null, 1.0, 2]}]'

json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]

So, serialization is on your side. It is done to have a better control over serialization. This means that '''if condition type is JSON_FIELD, ''add_condition'' function awaits string''' and '''after you get condition back, Condition.value contains string'''.

Example:

import json from rcdb.provider import RCDBProvider from rcdb.model import ConditionType

Create RCDBProvider provider object and connect it to DB

db = RCDBProvider("sqlite:///example.db")

Create condition type

db.create_condition_type("list_data", ConditionType.JSON_FIELD) db.create_condition_type("dict_data", ConditionType.JSON_FIELD)

list_to_store = [1, 2, 3] dict_to_store = {"x": 1, "y": 2, "z": 3}

Dump values to JSON and save it to DB to run 1

db.add_condition(1, "list_data", json.dumps(list_to_store)) db.add_condition(1, "dict_data", json.dumps(dict_to_store))

Get condition from database

restored_list = json.loads(db.get_condition(1, "list_data").value) restored_dict = json.loads(db.get_condition(1, "dict_data").value)

print restored_list print restored_dict

print restored_dict["x"] print restored_dict["y"] print restored_dict["z"]

The output is:

[1, 2, 3]
{u'y': 2, u'x': 1, u'z': 3}
1
2
3

The example is located at

$RCDB_HOME/python/example_conditions_store_array.py

and can be run as: python $RCDB_HOME/python/create_empty_sqlite.py example.db python $RCDB_HOME/python/example_conditions_store_array.py

As one can mention unicode string is returned as unicode after json deserialization (look at u"x" instead of just "x"). It is not a problem if you just work with this array, because python acts seamlessly with unicode strings. As you can see in example, we use usual string "x" in restored_dict["x"] and it just works.

If it is a problem, there is a http://stackoverflow.com/questions/956867/how-to-get-string-objects-instead-of-unicode-ones-from-json-in-python stackoverlow question on that

Using pyYAML to deserialize to strings looks easy.

=== Custom python objects ===

To save custom python objects to database, jsonpickle package could be used. It is an open source project available via pip install. It is not shipped with RCDB at the moment.

from rcdb.provider import RCDBProvider from rcdb.model import ConditionType import jsonpickle

class Cat(object): def init(self, name): self.name = name self.mice_eaten = 1230

Create RCDBProvider provider object and connect it to DB

db = RCDBProvider("sqlite:///example.db")

Create condition type

db.create_condition_type("cat", ConditionType.JSON_FIELD)

Create a cat and store in in the DB for run 1

cat = Cat('Alice') db.add_condition(1, "cat", jsonpickle.encode(cat))

Get condition from database for run 1

condition = db.get_condition(1, "cat") loaded_cat = jsonpickle.decode(condition.value)

print "How cat is stored in DB:" print condition.value print "Deserialized cat:" print "name:", loaded_cat.name print "mice_eaten:", loaded_cat.mice_eaten

The result:

How cat is stored in DB: {"py/object": "__main__.Cat", "name": "Alice", "mice_eaten": 1230} Deserialized cat: name: Alice mice_eaten: 1230

http://jsonpickle.github.io jsonpickle Documentation

jsonpickle installation:

system level:

pip install jsonpickle

user level:

pip install --user jsonpickle

=== STRING_FIELD vs. JSON_FIELD vs. BLOB_FIELD ===

What if data doesn't fit into the string or JSON? There is ConditionType.BLOB_FIELD type.

Concise instruction is much like JSON:

  • Set condition type as BLOB_FIELD
  • You serialize object whatever you like
  • Save it to DB as string
  • Load from DB
  • Deserialize whatever you like

But what is the difference between STRING_FIELD, JSON_FIELD and BLOB_FIELD?

There is no difference in terms of storing the data. A Condition class, same as a database table, has ''text_value'' field where text/string data is stored. The ONLY difference is how this fields are treated and presented in GUI.

  • '''STRING_FIELD''' - is considered to be a human readable string.

  • '''JSON_FIELD''' - is considered to be JSON, which is colored and formatted accordingly

  • '''BLOB_FIELD''' - is considered to be neither very readable string nor JSON. But it is still should converted to some string. And I hope it will never be used.