Classes and utility functions
This chapter provides descriptions of the classes and utility functions used to write custom show commands.
Formatters
A number of built-in formatters are available or you can create your own using the Format utilities:
Formats the data using a column-based table, which supports a number of ways to customize the look-and-feel.
ColumnFormatter
+----------+---------+-------------+
| entry-id | source | destination |
+==========+=========+=============+
| 10 | 1.2.3.4 | 5.6.7.8 |
+----------+---------+-------------+
Formats the data using a single tag: value pair on each line.
TagValueFormatter
entry-id : 10
source : 1.2.3.4
destination : 5.6.7.8
Formats the data using:
-
a single line to print the name and keys
-
a line for each field and leaf-list, formatted as a ‟tag: value” pair
TagValueWithKeylineFormatters
Entry 10
source : 1.2.3.4
destination : 5.6.7.8
Built-in decorators are also available to wrap around a formatter to add embellishments to the output. The following table lists the built-in decorators.
Built-in decorator |
Description |
---|---|
Adds an indentation before every output line. |
|
Adds lines above, below, or between the printed entries. |
|
Adds a header above the first printed entry. |
|
Adds a footer below the last printed entry. |
|
Adds an empty line above, below, or between the printed entries. |
|
Filters out fields/leaf-lists. |
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.
Column-based table
+----------+-------------------+--------------------+---------------+
| 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
The bool construct controls whether the ancestor keys are added as columns to the output table:
-
True - (the default) includes all ancestor keys
-
False - does not include any ancestor keys
A list provides more granular control. The list must contain a value for each ancestor key, and can contain:
-
None - suppresses the key
-
A string to specify the column key to use for the ancestor key
List with none value
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. The following table lists the 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 border type when drawing a table. Values can be combined together using the symbol ‛|’. For example: Borders.Outside | Borders.Header draws a border around the table and a line below the header. The following table defines the border values to use when drawing a table.
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 |
TagValueFormatter
Class srlinux.data.TagValueFormatter(filter=None)
Formats the specified Data object as a list of ‟tag: value” pairs (one on each line).
key : <name>
field: <value>
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).
node <name> id <id>
field: <value>
Indent
Class srlinux.data.Indent(formatter, indentation=' ')
Decorator that indents every line printed by the wrapped formatter.
Indent(MyOtherFormatter(), 6)
Indent(MyOtherFormatter(), ' ')
Either of the examples shown above adds six spaces before every line printed by MyOtherFormatter. The following table defines the 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. |
Border
Class srlinux.data.Border(formatter, position=None, character='-')
Decorator that prints a border line above, below, or above and below another formatter.
Border(MyOtherFormatter(), Border.Above | Border.Below, '+')
This example prints a border line of ++++++++++ above and below the output of the other formatter. The following table lists the 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 ‟-”. |
Header
Class srlinux.data.Header(formatter, text, character='-')
Decorator that prints a header above another formatter.
Header(
MyOtherFormatter(),
text='The header text',
character='+'
)
This example prints:
++++++++++++++++++++++++
The header text
++++++++++++++++++++++++
<snip here is the output of MyOtherFormatter>
The following table defines the 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 ‟-”. |
Footer
Class srlinux.data.Footer(formatter, text, character='-')
Decorator that prints a footer below another formatter.
Footer(
MyOtherFormatter(),
text='The footer text',
character='+'
)
This example prints:
<snip here is the output of MyOtherFormatter>
++++++++++++++++++++++++
The footer text
++++++++++++++++++++++++
The following table defines the 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 ‟-”. |
Whiteline
iClass srlinux.data.Whiteline(formatter, position=None)
Decorator that prints an empty line above, below, and between entries of another formatter.
Whiteline(MyOtherFormatter(), Whiteline.Above | Whiteline.Below)
This example prints an empty line above and below the output of the other formatter.
The following table defines the 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. |
FilteredFormatter
iClass srlinux.data.FilteredFormatter(formatter, schema, fields=[], leaflists=[])
Decorator that only displays the selected fields and leaf-lists.
FilteredFormatter
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.
For the next example, both the original fields and the combined field are added to the Data object, and the original fields are filtered out for formatting.
Both fields added to data object
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']
)
The following table defines the available 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. |
Format utilities
If the built-in formatters are not sufficient, you can add a summary line or other modifications. The following utilities can be used when writing your own Formatter.
ColumnPrinter
iClass 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.
+----------+-------------------+
| Entry id | Ip prefix |
+==========+===================+
| 1 | 1.1.2.0/24 |
| 2 | 1.1.2.2/32 |
+----------+-------------------+
This output is generated with the following:
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 |',
# '+----------+-------------------+'
# )
The following table defines the constructor arguments that can be used to customize the output.
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. |
TagValuePrinter
iClass srlinux.data.TagValuePrinter(tags, max_width, filter=None)
Utility class to print a set of ‟tag: value” pairs.
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',
# )
The following table defines the TagValuePrinter arguments.
Argument |
Description |
---|---|
filter : Filter |
Filters out fields/leaf-lists from the output. Fields that do not match the filter are not printed. |
TagValueWithKeyLinePrinter
iClass 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).
node <name> id <id>
field: <value>
The following is an example of this 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',
# )
The following table defines theTagValueWithKeyLinePrinter arguments.
Argument |
Description |
---|---|
filter : Filter |
Filters out fields/leaf-lists from the output. Fields that do not match the filter are not printed. |
print_line
srlinux.data.print_line(width, character='-')
Returns a line of length ‟width”, consisting of the specified character.
print_double_line
srlinux.data.print_double_line(width)
Returns a line of length ‟width” consisting of ============.
indent
srlinux.data.indent(values, indentation)
Indents each 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.
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.
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.
SchemaNode
Assume that this is the data model:
list interface {
key 'name';
field 'admin-state';
leaflist 'values';
list subinterface {
key 'id';
}
}
You can then:
-
Get the keys:
value = data.name
-
Get and set the fields:
value = data.admin_state # returns the value or None if unset data.admin_state = 'enabled'
-
Get and set leaflists:
value = data.values # returns a list data.values = ['a', 'b']
-
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
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:
-
bool
-
integer
-
string
Formatters
To generate the show report, Formatter objects are used. These can be tied to a specific Data object using two methods:
-
By assigning a formatter to the Data.formatter property.
-
By using Data.set_formatter().
Both methods assign the formatter to all sibling Data objects. Calling the following sets the formatter for all interfaces and not just for subinterface 42.
Formatters
data.subinterface.get(42).formatter = ColumnFormatter()
The following table lists the different 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 specified 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 specified 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”. |
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.
No keys
If the schema has no keys, use:
data.node.get()
data.node.create()
data.node.exists()
Single key
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')
Multiple keys
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)
The following table defines the 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 specified, 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. |
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.
The following table defines the SchemaNode 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. |