gc3libs.persistence.accessors

Accessors for object attributes and container items.

class gc3libs.persistence.accessors.GetAttributeValue(attr, xform=<function <lambda>>, default=<object object>)

Return an accessor function for the given attribute.

An instance of GetAttributeValue is a callable that, given any object, returns the value of its attribute attr, whose name is specified in the GetAttributeValue constructor:

>>> from gc3libs import Struct
 >>> fn = GetAttributeValue('x')
 >>> a = Struct(x=1, y=2)
 >>> fn(a)
 1

The accessor raises AttributeError if no such attribute exists):

>>> b = Struct(z=3)
>>> fn(b)
Traceback (most recent call last):
   ...
AttributeError: 'Struct' object has no attribute 'x'

However, you can specify a default value, in which case the default value is returned and no error is raised:

>>> fn = GetAttributeValue('x', default=42)
>>> fn(b)
42
>>> fn = GetAttributeValue('y', default=None)
>>> print(fn(b))
None

In other words, if fn = GetAttributeValue(‘x’), then fn(obj) evaluates to obj.x.

If the string attr contains any dots, then attribute lookups are chained: if fn = GetAttributeValue(‘x.y’) then fn(obj) evaluates to obj.x.y:

>>> fn = GetAttributeValue('x.y')
>>> a = Struct(x=Struct(y=42))
>>> fn(a)
42

The optional second argument xform allows composing the accessor with an arbitrary function that is passed an object and should return a (possibly different) object whose attributes should be looked up. In other words, if xform is specified, then the returned accessor function computes xform(obj).attr instead of obj.attr.

This allows combining GetAttributeValue with GetItemValue() (which see), to access objects in deeply-nested data structures; see GetItemValue for examples.

class gc3libs.persistence.accessors.GetItemValue(place, xform=<function <lambda>>, default=<object object>)

Return accessor function for the given item in a sequence.

An instance of GetItemValue is a callable that, given any sequence/container object, returns the value of the item at its place idx:

>>> fn = GetItemValue(1)
>>> a = 'abc'
>>> fn(a)
'b'
>>> b = { 1:'x', 2:'y' }
>>> fn(b)
'x'

In other words, if fn = GetItemValue(x), then fn(obj) evaluates to obj[x].

Note that the returned function fn raises IndexError or KeyError, (depending on the type of sequence/container) if place idx does not exist:

>>> fn = GetItemValue(42)
>>> a = list('abc')
>>> fn(a)
Traceback (most recent call last):
   ...
IndexError: list index out of range
>>> b = dict(x=1, y=2, z=3)
>>> fn(b)
Traceback (most recent call last):
   ...
KeyError: 42

However, you can specify a default value, in which case the default value is returned and no error is raised:

>>> fn = GetItemValue(42, default='foo')
>>> fn(a)
'foo'
>>> fn(b)
'foo'

The optional second argument xform allows composing the accessor with an arbitrary function that is passed an object and should return a (possibly different) object where the item lookup should be performed. In other words, if xform is specified, then the returned accessor function computes xform(obj)[idx] instead of obj[idx]. For example:

>>> c = 'abc'
>>> fn = GetItemValue(1, xform=(lambda s: s.upper()))
>>> fn(c)
'B'

>>> c = (('a',1), ('b',2))
>>> fn = GetItemValue('a', xform=dict)
>>> fn(c)
1

This allows combining GetItemValue with GetAttrValue (which see), to access objects in deeply-nested data structures.

class gc3libs.persistence.accessors.GetOnly(only, xform=<function <lambda>>, default=<object object>)

Apply accessor function to members of a certain class; return a default value otherwise.

The GetOnly accessor performs just like GetValue, but is effective only on instances of a certain class; if the accessor function is passed an instance of a different class, the default value is returned:

>>> from gc3libs import Struct
>>> fn4 = GetOnly(Struct, default=42)
>>> isinstance(fn4(Struct(foo='bar')), Struct)
True
>>> isinstance(fn4(dict(foo='bar')), dict)
False
>>> fn4(dict(foo='bar'))
42

If default is not specified, then None is returned:

>>> fn5 = GetOnly(Struct)
>>> repr(fn5(dict(foo='bar')))
'None'
class gc3libs.persistence.accessors.GetValue(default=<object object>)

Provide easier compositional syntax for GetAttributeValue and GetItemValue.

Instances of GetAttributeValue and GetItemValue can be composed by passing one as xform parameter to the other; however, this results in the writing order being the opposite of the composition order: for instance, to create an accessor to evaluate x.a[0] for any Python object x, one has to write:

>>> from gc3libs import Struct
>>> fn1 = GetItemValue(0, GetAttributeValue('a'))

The GetValue class allows to write accessor expressions the way they are normally written in Python:

>>> GET = GetValue()
>>> fn2 = GET.a[0]
>>> x = Struct(a=[21,42], b='foo')
>>> fn1(x)
21
>>> fn2(x)
21

The optional default argument specifies a value that should be used in case the required attribute or item is not found:

>>> fn3 = GetValue(default='no value found').a[3]
>>> fn3(x)
'no value found'
ONLY(specifier)

Restrict the action of the accessor expression to members of a certain class; return default value otherwise.

The invocation to only() should always be last:

>>> from gc3libs import Struct
>>> fn = GetValue(default='foo').a[0].ONLY(Struct)
>>> fn(Struct(a=['bar','baz']))
'bar'
>>> fn(dict(a=['bar','baz']))
'foo'

If it’s not last, you will get AttributeError like the following:

>>> fn = GetValue().ONLY(Struct).a[0]
>>> fn(dict(a=[0,1]))
Traceback (most recent call last):
  ...
AttributeError: 'NoneType' object has no attribute 'a'