Groups

Parameter groups in general describe associations of multiple parameters and the way they interact with each other. For example:

from hanna import Configurable, Group, Integer

class Rectangle(Configurable):
    dimensions = Group(Integer('width'), Integer('height'))
    
r = Rectangle(dict(width=2, height=3))
r.dimensions  # {'width': 2, 'height': 3}

Internally parameter groups are converted to a dict with the group member names as keys and their loaded specifications as values.

Using different containers

By default Group uses a dict as container for its members (after loading). We can customize this:

from collections import namedtuple

class Rectangle(Configurable):
    dim_type = namedtuple('dimensions', ['width', 'height'])
    dimensions = Group(Integer('width'), Integer('height'), as_=dim_type)
    del dim_type
    
r = Rectangle(dict(width=2, height=3))
r.dimensions  # dimensions(width=2, height=3)
r.dimensions.width, r.dimensions.height  # (2, 3)

Any object obj that supports obj(**member_dict) argument expansion as well as tuple and list can be used as the containing data structure. For tuple and list the member names are dropped but the order in which they were declared is maintained.

Transformations

Transformations can be applied to Groups in a similar way that they are applied to parameters (see Transformations). For example:

class Rectangle(Configurable):
    area = Group(
        Integer('width'), Integer('height'),
        as_=tuple
    ) >> (lambda x: x[0]*x[1])
    
r = Rectangle(dict(width=2, height=3))
r.area  # 6

Sections

Groups can be assigned to separate sections similar to Class Sections but with the difference that the specified section won't be used to modify the members' names but instead to concatenate section and name when loading the parameter. For example:

from pyhocon import ConfigFactory

class Rectangle(Configurable):
    # The `name` keyword argument is used to specify group sections.
    dimensions = Group(Integer('width'), Integer('height'), name='square')
    
r = Rectangle(ConfigFactory.parse_string(
    """square {
            width = 2
            height = 3
        }"""
))
# Section names are not prepended to parameter names.
r.dimensions  # {'width': 2, 'height': 3}

Adding members

Parameters can be add to an existing group in the following ways:

group = Group(Integer('i'))
group += Integer('j')
group.add(Integer('k'))

Extending groups

Existing groups can be extended by others in the following way:

rectangle = Group(Integer('width'), Integer('height'), name='square')
color = Group(Integer('r'), Integer('g'), Integer('b'), name='color')
rectangle.extend(color)

When extending a group it retains its original name / section and modifies the names of the other group's parameters by prepending the other group's name / section to the other group's members. Let's have a closer look:

rectangle.name  # "square"
rectangle.members[0].name  # "width"
rectangle.members[-1].name  # "color.b"

In order to load the the group we can provide the following HOCON file:

square {
    width = 2
    height = 3
    color {
        r = 32
        g = 64
        b = 128
    }
}
>> rectangle.load(ConfigFactory.parse_file('/path/to/config'))
{'width': 2, 'height': 3, 'color.r': 32, 'color.g': 64, 'color.b': 128}

Last updated