4. Classes and utility functions

This chapter provides detailed descriptions of all the classes and utility functions used to write custom show commands.

4.1. Formatters

There are a number of built-in formatters to choose from (or create your own using the Format utilities):

ColumnFormatter:

Formats the data using a column-based table, which supports a number of ways to customize the look-and-feel.

Example:

+----------+---------+-------------+
| entry-id | source  | destination |
+==========+=========+=============+
| 10       | 1.2.3.4 | 5.6.7.8     |
+----------+---------+-------------+

TagValueFormatter:

Formats the data using a single tag: value pair on each line.

Example:

entry-id    : 10
source      : 1.2.3.4
destination : 5.6.7.8

TagValueWithKeyLineFormatter:

Formats the data using:

  1. a single line to print the name and keys
  2. a line for each field and leaf-list, formatted as a “tag: value” pair

Example:

Entry 10
  source      : 1.2.3.4
  destination : 5.6.7.8

There are also built-in decorators which you can wrap around a formatter to add embellishments to the output. Table 2 lists the built-in decorators.

Table 2:  Built-in decorators  

Built-in decorator

Description

Indent

Adds an indentation before every output line.

Border

Adds lines above, below, or between the printed entries.

Header

Adds a header above the first printed entry.

Footer

Adds a footer below the last printed entry.

Whiteline

Adds an empty line above, below, or between the printed entries.

FilteredFormatter

Filters out fields/leaf-lists.

4.1.1. ColumnFormatter

Class srlinux.data.ColumnFormatter(ancestor_keys=True, horizontal_alignment=None, vertical_alignment=None, borders=None

Formats the specific Data object as a column-based table.

Example output:

+----------+-------------------+--------------------+---------------+
| Entry id |     Ip prefix     |  Origin protocol   |   Next hop    |
+==========+===================+====================+===============+
| 1        | 1.1.2.0/24        | local_aggregate    | None          |
| 2        | 1.1.2.2/32        | directly_connected | None          |
+----------+-------------------+--------------------+---------------+

The output can be customized using the following constructor arguments:

ancestor_keys : bool or list

  1. Controls whether the ancestor keys will be added as columns to the output table
  2. True - (the default) includes all ancestor keys
  3. False - does not include any ancestor keys
  4. A list provides more granular control. The list must contain a value for each ancestor key, and can contain:
    1. None - suppresses the key
    2. A string to specify the column key to use for the ancestor key
    For example, when passed [None, “A”, None], the first and third ancestor key are dropped, and the second is renamed to “A”.

horizontal_alignment : dict{str: Alignment}

Dictionary mapping column-names to their horizontal alignment (Alignment.Left/Center/Right). Columns not mentioned are left-aligned.

vertical_alignment : dict{str: Alignment}

Dictionary mapping column-names to their vertical alignment (Alignment.Top/Middle/Bottom). Columns not mentioned are top-aligned.

borders : Borders

Combination of Borders values indicating which borders to print. Defaults to “Borders.Outside | Borders.Header | Borders.Columns”.

Class srlinux.data.Alignment

The values used to align data in the table cells. Table 3 lists the alignment values.

Table 3:  Cell alignment values  

Alignment value

Description

Left= 1

Horizontally aligns the data to the left

Right= 2

Horizontally aligns the data to the right

Center= 3

Horizontally centers the data

Top= 4

Vertically aligns the data to the top

Middle= 5

Vertically centers the data

Bottom= 6

Vertically aligns the data to the bottom

Class srlinux.data.Borders

Specifies which borders to draw when drawing the table. Values can be combined together using the symbol ‘|’. For example: Borders.Outside | Borders.Header draws a border around the table and line below the header. Table 4 defines the border values to use when drawing a table.

Table 4:  Types of table borders 

Table border

Description

Nothing= 0

Draws no borders

Outside= 1

Draws a border around the table

Header= 2

Draws a horizontal line between the header and the first row

Rows= 4

Draws a horizontal line between the rows

Columns= 8

Draws a vertical line between the columns

4.1.2. TagValueFormatter

Class srlinux.data.TagValueFormatter(filter=None)

Formats the specified Data object as a list of “tag: value” pairs (one on each line).

Example output:

key  : <name>
field: <value>

4.1.3. TagValueWithKeyLineFormatter

Class srlinux.data.TagValueWithKeyLineFormatter(filter=None)

Formats the specified Data object as a single line with the name and the keys, followed by a list of “tag: value” pairs (one on each line).

Example output:

node <name> id <id>
 field: <value>

4.1.4. Indent

Class srlinux.data.Indent(formatter, indentation=' ')

Decorator that indents every line printed by the wrapped formatter.

Example usage:

Indent(MyOtherFormatter(), 6)
Indent(MyOtherFormatter(), '      ')

Either example adds six spaces before every line printed by MyOtherFormatter.

Table 5 defines the indent arguments.

Table 5:  Indent arguments  

Argument

Description

indentation: str or int

The indent string put before every line, or an integer that indicates the amount of spaces to add.

4.1.5. Border

Class srlinux.data.Border(formatter, position=None, character='-')

Decorator that prints a border line above, below, or above and below another formatter.

Example usage:

Border(MyOtherFormatter(), Border.Above | Border.Below, '+')

This example prints a border line of ++++++++++ above and below the output of the other formatter.

Table 6 lists the border line arguments.

Table 6:  Border line arguments  

Argument

Description

position : Border

Controls where the border lines are drawn. Multiple values can be combined together using the “|” symbol.

Border.Above

Prints a line above the first Data entry. Defaults to printing a line above and below.

Border.Below

Prints a line below the last Data entry. Defaults to printing a line above and below.

Border.Between

Prints a line between each Data entry. Defaults to printing a line above and below.

character: char (optional)

Defines the character used to draw the border line. Defaults to “-”.

4.1.6. Header

Class srlinux.data.Header(formatter, text, character='-')

Decorator that prints a header above another formatter.

Example usage:

Header(
    MyOtherFormatter(),
    text='The header text',
    character='+'
)

This example prints:

++++++++++++++++++++++++
The header text
++++++++++++++++++++++++
<snip here is the output of MyOtherFormatter>

Table 7 defines the header arguments.

Table 7:  Header arguments  

Argument

Description

text: str

Defines the header text, which can contain new lines.

character: char (optional)

Defines the character used to draw the border. Defaults to “-”.

4.1.7. Footer

Class srlinux.data.Footer(formatter, text, character='-')

Decorator that prints a footer below another formatter.

Example usage:

Footer(
    MyOtherFormatter(),
    text='The footer text',
    character='+'
)

This example prints:

<snip here is the output of MyOtherFormatter>
++++++++++++++++++++++++
The footer text
++++++++++++++++++++++++

Table 8 defines the footer arguments.

Table 8:  Footer arguments 

Argument

Description

text: str

Defines the footer text, which can contain new lines.

character: char

Defines the character used to draw the border. Defaults to “-”.

4.1.8. Whiteline

Class srlinux.data.Whiteline(formatter, position=None)

Decorator that prints an empty line above, below, and between entries of another formatter.

Example usage:

Whiteline(MyOtherFormatter(), Whiteline.Above | Whiteline.Below)

This example prints an empty line above and below the output of the other formatter.

Table 9 defines the Whiteline arguments.

Table 9:  Whiteline arguments  

Argument

Description

position : Whiteline

Controls where the empty lines are drawn. Multiple values can be combined together using “|”.

Whiteline.Above

Prints a line above the first Data entry. Defaults to printing a line above and below.

Whiteline.Below

Prints a line below the last Data entry. Defaults to printing a line above and below.

Whiteline.Between

Prints a line between each Data entry. Defaults to printing a line above and below.

4.1.9. FilteredFormatter

Class srlinux.data.FilteredFormatter(formatter, schema, fields=[], leaflists=[])

Decorator that only displays the selected fields and leaf-lists.

Example usage:

FilteredFormatter(
    MyOtherFormatter(),
    schema=data.schema,
    fields=['field-to-keep', 'other-field-to-keep'],
    leaflists=['leaflist-to-keep', 'other-leaflist-to-keep'],
)

A common use case for this decorator is to enhance the format of some fields, but keeps the original field values available for when the output is formatted as JSON.

In this case, add both the original fields and the combined field to the Data object, and filter the original fields out for formatting.

data = Data(schema)
 
# The 2 original fields. Added to data so that 'show <snip> | as json' displays them
 in a useful fashion.
data.source = '1.2.3.4'
data.destination = '5.6.7.8'
 
# The combined field we want to show in the show report.
data.flow = f'{data.source} -> {data.destination}'
 
# Only show the combined field in the show report.
data.formatter = FilteredFormatter(
    TagValueFormatter(),
    schema=data.schema,
    fields=['flow']
)

Table 10 defines the available FilteredFormatter arguments.

Table 10:  FilteredFormatter arguments  

Argument

Description

schema : SchemaNode

Defines the schema of the Data object this formatter is applied to

fields : list of str

Defines the names of the fields to display. Any field not mentioned is omitted from the output. The default is to remove all fields.

leaflists : list of str

Defines the names of the leaf-lists to display. Any leaf-list not mentioned is omitted from the output. The default is to remove all leaf-lists.

4.2. Format utilities

If the built-in formatters are not sufficient, you can add a summary line or other modifications.

To help with this, the following utilities can be used when writing your own Formatter.

4.2.1. ColumnPrinter

Class srlinux.data.ColumnPrinter(columns, max_width, horizontal_alignment, vertical_alignment, borders, filter=None)

Utility class to print a set of rows as a column-based table.

Example output:

+----------+-------------------+
| Entry id |     Ip prefix     |
+==========+===================+
| 1        | 1.1.2.0/24        |
| 2        | 1.1.2.2/32        |
+----------+-------------------+

Usage:

printer = ColumnPrinter(['Entry id', 'Ip prefix'], borders=Borders.Outside, max_widt
h=80)
 
printer.add_row([1, '1.1.2.0/24'])
printer.add_row([2, '1.1.2.2/32'])
 
printer.iter_format()
# Returns
# (
#    '+----------+-------------------+',
#    '| Entry id |     Ip prefix     |',
#    '+==========+===================+',
#    '| 1        | 1.1.2.0/24        |',
#    '| 2        | 1.1.2.2/32        |',
#    '+----------+-------------------+'
# )

Table 11 defines the constructor arguments that can be used to customize the output.

Table 11:  ColumnPrinter constructor arguments   

Constructor argument

Description

horizontal_alignment : dict{str: Alignment}

Dictionary mapping of column-names to their horizontal alignment (Alignment.Left/Center/Right). Columns not mentioned here are left-aligned.

vertical_alignment : dict{str: Alignment}

Dictionary mapping of column-names to their vertical alignment (Alignment.Top/Middle/Bottom). Columns not mentioned here are top-aligned.

borders : Borders

Combining borders values that indicate what borders can be drawn. Defaults to “Borders.Outside | Borders.Header | Borders.Columns”.

filter : Filter

Filters out fields from the output. Fields that do not match the filter are not printed.

4.2.2. TagValuePrinter

Class srlinux.data.TagValuePrinter(tags, max_width, filter=None)

Utility class to print a set of “tag: value” pairs.

Usage:

printer = TagValuePrinter(['first', 'second'], max_width=80)
printer.iter_format(['value', 'other-value'])
# Returns (
#    'first : value',
#    'second: other-value',
# )

If None (or ‘’ or []) is passed in as a value, the item is skipped in the output:

printer.iter_format([None, 'other-value'])
# Returns (
#    'second: other-value',
# )

Table 12 defines the TagValuePrinter arguments.

Table 12:  TagValuePrinter arguments  

Argument

Description

filter : Filter

Filters out fields/leaf-lists from the output. Fields that do not match the filter are not printed.

4.2.3. TagValueWithKeyLinePrinter

Class srlinux.data.TagValueWithKeyLinePrinter(name, keys, tags, max_width, filter=None)

Utility class to print a single line with the name and the keys, followed by a list of “tag: value” pairs (one on each line).

Example output:

node <name> id <id>
 field: <value>

Usage:

printer = TagValueWithKeyLinePrinter(name='node', keys=['key'], tags=['first-
field', 'second-field'], max_width=80)
printer.iter_format(keys=[<name>], values=['value', 'other-value'])
# Returns (
#    'node <name>',
#    '  first-field : value',
#    '  second-field: other-value',
# )

If None (or ‘’ or []) is passed in as a value, the item is skipped in the output:

printer.iter_format(keys=['<name>'], [None, 'other-value'])
# Returns (
#    'node <name>',
#    '  second-field: other-value',
# )

Table 13 defines theTagValueWithKeyLinePrinter arguments.

Table 13:  TagValueWithKeyLinePrinter arguments   

Argument

Description

filter : Filter

Filters out fields/leaf-lists from the output. Fields that do not match the filter are not printed.

4.2.4. print_line

srlinux.data.print_line(width, character='-')

Returns a line of length “width”, consisting of the specified character.

4.2.5. print_double_line

srlinux.data.print_double_line(width)

Returns a line of length “width” consisting of ============.

4.2.6. indent

srlinux.data.indent(values, indentation)

Indents each given value with the specified indentation. The indentation can either be a string, or an integer indicating the number of spaces to use for the indentation.

4.2.7. format_value

srlinux.data.format_value(value)

Formats the Data value as a string, which works for key, field, and leaf-list values of all accepted types (number, string, bool), even if the field/leaf-list is absent.

4.3. Data

The class used to represent all data; both the data retrieved from the server and the data displayed in the show report.

Class srlinux.data.data.Data(schema, parent=None, **keys)

Allows easy access to a configuration/state instance. When creating a top-level Data object, you must specify an instance of a SchemaNode. The code analyzes the schema, and makes all fields, keys, leaf-lists, and children accessible as attributes.

For example, assume that this is the data model:

list interface {
    key 'name';
    field 'admin-state';
    leaflist 'values';
    list subinterface {
        key 'id';
    }
}

You can then:

  1. Get the keys:
    value = data.name
  2. Get and set the fields:
    value = data.admin_state # returns the value or None if unset
    data.admin_state = 'enabled'
  3. Get and set leaflists:
    value = data.values # returns a list
    data.values = ['a', 'b']
  4. Access children:
    child = data.subinterface.create(42) # Creates the subinterface with id '42'
    child = data.subinterface.get(42)
    if data.subinterface.exists(42):
        # Returns True/False
    for si in data.subinterface.items():
        # Walks all subinterfaces, ordered by their key
Note:

Names are changed so that any character that is not a to z, A to Z, or 0 to 9 is replaced by an “_”.

Children

When accessing a child (data.subinterface in the preceding example), an instance of DataChildrenOfType is returned. Follow the link to see all the accessors it provides.

Values

All key/field/leaf-list values are of the following types:

  1. bool
  2. integer
  3. string

Formatters

To generate the show report, Formatter objects are used. These can be tied to a specific Data object using two methods:

  1. By assigning a formatter to the Data.formatter property.
  2. By using Data.set_formatter().

Both methods assign the formatter to all sibling Data objects. For example, calling the following sets the formatter for all interfaces and not just for subinterface 42.

data.subinterface.get(42).formatter = ColumnFormatter()

Table 14 flists the different types of formatters.

Table 14:  Types of formatters  

Formatter

Description

parent

Returns the parent Data object, or None if this is the root.

schema

Returns the SchemaNode.

key_names

Returns an iterator over the names of the keys.

key_values

Returns an iterator over the key values. Iterators are returned in the order specified by self.key_names, which is the same as the order that the keys were added to the SchemaNode.

get_key(name)

Returns the value of the key with the given name.

keys_dict

Returns a “name: value” dictionary of the keys.

type_name

Returns the type-name, which is self.schema.name.

field_names

Returns an iterator over the names of the fields.

field_values

Returns an iterator over the field values. Iterators are returned in the order specified by self.field_names, which is the same as the order that the fields were added to the SchemaNode.

set_field(name, value)

Assigns the value to the field with the given name.

get_field(name, default=None)

Returns the value of the field with the specified name, or the default if the field is unset.

is_field_set(name)

Returns True if the field is set.

leaflist_names

Returns an iterator over the names of the leaf-lists.

leaflist_values

Returns an iterator over the leaf-list values. Iterators are returned in the order specified by self.leaflist_names, which is the same as the order that the leaf-lists were added to the SchemaNode.

get_leaflist(name)

Returns a list containing the values of the leaf-list with the specified name. This list is empty if the leaf-list is unset.

set_leaflist(name, value)

Assigns the value to the leaf-list with the specified name. The value must be a list.

is_leaflist_set(name)

Returns True if the leaf-list is set.

child_names

Returns an iterator over the names of the children.

get_children(name)

Returns the DataChildrenOfType instance that contains all the children of the specified type. This returned object is mutable and can be used to walk/retrieve/add children.

iter_children_by_type(predicate=<function Data.<lambda>>)

Iterates over all DataChildrenOfType instances for which the predicate is True. By default, this returns all children.

iter_children()

Iterates over all child instances.

get(name)

Returns the value of the specified key, field, leaf-list, or child.

get_annotations(name=None)

Returns a list containing the annotations of this node (if called with no arguments) or the field with the specified name.

add_annotation(annotation, name=None)

Adds the specified annotation to this node (when called with a single argument) or to the field with the specified name (when called with two arguments). The annotation must be an instance of Annotation.

formatter

Returns the Formatter that can be used to generate the show report for this Data object.

iter_format(max_width)

Invokes the Formatter of this Data object. Returns an iterator over the formatted output lines.

iter_format_children(max_width)

Invokes the Formatter of all children of this Data object. Returns an iterator over the formatted output lines.

set_formatter(schema, formatter)

Adds a Formatter to the Data object with the specified schema. The schema can be specified as an XPath string (without keys). For example, “/interface/subinterface”.

get_schema(path)

Get the SchemaNode of the Data object with the specified path. The path must be an XPath string, for example, “/interface/subinterface”.

4.4. DataChildrenOfType

Use this class when you need to access children through a Data object. It allows you to retrieve, create, and iterate all children.

Class srlinux.data.data.DataChildrenOfType(schema, parent)

The children of a Data object of a single type.

Returned by Data.get_children() or by accessing the attribute with the child name (for example, Data.interface). Most methods require you to pass a value for each key defined in the schema.

For example, if the schema has no keys, use:

data.node.get()
data.node.create()
data.node.exists()

If the schema has a single key, this becomes:

#node has a single key 'name'
 
data.node.get('abc')
data.node.create('abc')
data.node.exists('abc')
 
# or
 
data.node.get(name='abc')
data.node.create(name='abc')
data.node.exists(name='abc')

If the schema has a multiple keys, specify them all in the correct order:

# node has 2 keys, 'name' and 'id'
 
data.node.get('abc', 1)
data.node.create('abc', 1)
data.node.exists('abc', 1)
 
# or
 
data.node.get(name='abc', id=1)
data.node.create(name='abc', id=1)
data.node.exists(name='abc', id=1)

Table 15 defines the DataOfChildrenType Attributes.

Table 15:  DataOfChildrenType attributes 

Attribute

Description

get(*args, **kwargs)

Returns an existing child with the specified keys. Generates an AttributeError if a wrong number of keys is given, and KeyError if there is the child does not exist.

exists(*args, **kwargs)

Returns True if a child with the specified keys exists. Generates an AttributeError if a wrong number of keys is given.

create(*args, **kwargs)

Creates and returns a child with the specified keys. If this child already exists, the existing child is returned (and no changes are made). Generates an AttributeError if a wrong number of keys is given.

count()

Counts the number of children.

is_empty

Returns True if there are no children of this type.

items()

Iterates over all children of this type and are sorted based on their keys.

clear()

Removes all children of this type.

formatter

Returns the Formatter that can be used to generate the show report for the Data object.

iter_format(max_width)

Invokes the Formatter.iter_format_type() of these Data objects. Returns an iterator over the formatted output lines.

4.5. SchemaNode

srlinux.schema.fixed_schema.FixedSchemaNode.add_child(self, child_name, key=None, keys=[], field=None, fields=[], leaflist=None, leaflists=[], importance=<ShowImportance.High: 3>)

Adds a list/container to the current node, which allows you to specify the keys, fields, and leaf-lists of the new child.

Table 16 defines the SchemaNode arguments.

Table 16:  Schema Node arguments  

Argument

Description

child_name : str

The name specified for the newly created child.

key : str or None

If not None, a key with the specified name is added.

keys : list of str

The names of the keys to be added.

field : str or None

If not None, a field with the specified name is added.

fields : list of str

The names of the fields that are added.

leaflist : str or None

If not None, a leaf-list with the specified name is added.

leaflists : list of str

The names of the leaf-lists to be added.