2.4.1 General properties

Now you can start entering property records into the database. A property record is a lot like a Python dict object, and thus it can contain nearly anything. It is implemented however as a CascadingDict object, which means that the key values are strings and can also be used as attributes to address the value. Thus, if P is a property record, then a field named key can either be addressed as P['key'] or as P.key. This implementation was choosen for the convenience of the user, but has no further advantages over a normal dict object. You should not use any of the methods of Python's dict class as key in a property record: it would override this method for the object.

The property record has four more reserved (forbidden) keys: kind, tag, set, setname and nr. The kind and nr should never be set nor changed by the user. kind is used internally to distinguish among different kind of property records (see 2.4.4). It should only be used to extend the PropertyDB class with new kinds of properties, e.g. in subclasses. nr will be set automatically to a unique record number. Some application modules use this number for identification and to create automatic names for property sets.

The tag, set and setname keys are optional fields and can be set by the user. They should however only be used for the intended purposes explained hereafter, because they have a special meaning for the database methods and application modules.

The tag field can be used to attach an identification string to the property record. This string can be as complex as the user wants and its interpretation is completely left to the user. The ProeprtyDB class just provides an easy way to select the records by their tag name or by a set of tag names. The set and setname fields are treated further in 2.4.2.

So let's create a property record in our database. The Prop() method does just that. It also returns the property record, so you can directly use it further in your code.

>>> Stick = P.Prop(color='green',name='Stick',weight=25, \
        comment='This could be anything: a gum, a frog, a usb-stick,...'})
>>> print Stick

  color = green
  comment = This could be anything: a gum, a frog, a usb-stick,...
  nr = 0
  name = Stick
  weight = 25
Notice the auto-generated nr field. Here's another example, with a tag:
>>> author = P.Prop(tag='author',name='Alfred E Neuman',\
        address=CascadingDict({'street':'Krijgslaan', 'city':'Gent','country':'Belgium'}))
>>> print author

  nr = 1
  tag = author
  name = Alfred E Neuman
  address = 
    city = Gent
    street = Krijgslaan
    country = Belgium
This example shows that record values can be complex structured objects. Notice how the CascadingDict object is by default printed in a very readible layout, offsetting each lower level dictionary two more postions to the right.

The CascadingDict has yet another fine characteristic: if an attribute is not found in the toplevel, all values that are instances of CascadingDict or Dict (but not the normal Python dict) will be searched for the attribute. If needed, this searching is even repeated in the values of the next levels, and further on, thus cascading though all levels of CascadingDict structures until the attribute can eventually be found. The cascading does not proceed through values in a Dict. An attribute that is not found in any of the lower level dictionaries, will return a None value.

If you set an attribute of a CascadingDict, it is always set in the toplevel. If you want to change lower level attributes, you need to use the full path to it.

>>> print author.street
  Krijgslaan
>>> author.street = 'Voskenslaan'
>>> print author.street
  Voskenslaan
>>> print author.address.street
  Krijgslaan
>>> author.address.street = 'Wiemersdreef'
>>> print author.address.street
  Wiemersdreef
>>> author = P.Prop(tag='author',alias='John Doe',\
        address={'city': 'London', 'street': 'Downing Street 10', 'country': 'United Kingdom'})
>>> print author

  nr = 2
  tag = author
  alias = John Doe
  address = {'city': 'London', 'street': 'Downing Street 10', 'country': 'United Kingdom'}

In the examples above, we have given a name to the created property records, so that we could address them in the subsequent print and field assigment statements. In most cases however, it will be impractical and unnecessary to give your records a name. They all are recorded in the PropertyDB database, and will exist as long as the database variable lives. There should be away though to request selected data from that database. The getProp() method returns a list of records satisfying some conditions. The examples below show how it can be used.

>>> for p in P.getProp(rec=[0,2]):
        print p.name
Stick
John Doe
>>>  for p in P.getProp(tag=['author']):
        print p.name
None
John Doe
>>>  for p in P.getProp(attr=['name']):
        print p.nr
0
2
>>>  for p in P.getProp(tag=['author'],attr=['name']):
        print p.name
John Doe
The first call selects records by number: either a single record number or a list of numbers can be specified. The second method selects records based on the value of their tag field. Again a single tag value or a list of values can be specified. Only those records having a 'tag' filed matching any of the values in the list will be returned. The third selection method is based on the existence of some attribute names in the record. Here, always a list of attribute names is required. Records are returned that posess all the attributes in the list, independent from the value of those attributes. If needed, the user can add a further filtering based on the attribute values. Finally, as is shown in the last example, all methods of record selection can be combined. Each extra condition will narrow the selection further down.