pyats.utils package

Submodules

pyats.utils.ansi.escape(line)

escape ansi by removing escape sequences.

Utilities to help with tricky CLI command parsing

pyats.utils.cli_parse_helpers.expand_nargs_list(nargs_list)

Expands an argparse nargs list of strings.

Any single or double quotes are stripped from the items.

NOTE: The ordering of the output list is not guaranteed to match the ordering of the input list.

Duplicates are removed from the list.

If the input list is empty, it is just returned without further processing.

Example

>>> import argparse
>>> from pyats.utils.cli_parse_helpers import expand_nargs_list
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='*')
>>> p = parser.parse_args('--foo 4 5 6 "1 2 3 4" x y 5 '.split())
>>> sorted(expand_nargs_list(p.foo))
['1', '2', '3', '4', '5', '6', 'x', 'y']
pyats.utils.cli_parse_helpers.remove_dups_from_multiple_nargs_list(multiple_nargs_list)

Ensure dups are removed from a list of nargs lists. Empty lists are removed.

>>> import argparse
>>> from pyats.utils.cli_parse_helpers import expand_nargs_list, remove_dups_from_multiple_nargs_list
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='*', action='append')
>>> p = parser.parse_args('--foo 4 5 6 "1 2 3 4" x y 5 --foo 2 4 6 8'.split())
>>> remove_dups_from_multiple_nargs_list([sorted(expand_nargs_list(foo)) for foo in p.foo])
[['1', '2', '3', '4', '5', '6', 'x', 'y'], ['8']]
class pyats.utils.commands.DecodeSecret(*args, **kwargs)

Bases: pyats.cli.base.Subcommand

description = '\nDecodes an encoded string into plaintext form.\n\nThe decoding used may be changed by specifying the pyats configuration:\n[secrets] string.representer = representer_module.representer_class\n\nOtherwise, a default cipher encoding is expected.\n\nThe decoding may be personalized by using the pyats configuration:\n[secrets] string.key = <generated_key>\n\nwhere <generated_key> refers to the key generated with the "pyats secret keygen"\ncommand.\n\nIf specified, --prefix selects other representers defined in the pyats\nconfiguration.  The following keys are expected to be present:\n[secrets] <prefix>.representer\n[secrets] <prefix>.key\n    '
help = 'decode an encoded string'
name = 'decode'
run(args)

runs this subcommand

usage = '{prog} [string] [options]'
class pyats.utils.commands.EncodeSecret(*args, **kwargs)

Bases: pyats.cli.base.Subcommand

description = '\nEncodes a plaintext string into an encoded form. By default, it will ask to\ninput password as prompt(Recommended).\nInstead, `--string` can be given with plaintext password.\n\nThe encoding used may be changed by specifying the pyats configuration:\n[secrets] string.representer = representer_module.representer_class\n\nOtherwise, a default cipher encoding is used.\n\nThe encoding may be personalized by using the pyats configuration:\n[secrets] string.key = <generated_key>\n\nwhere <generated_key> refers to the key generated with the "pyats secret keygen"\ncommand.\n\nIf specified, --prefix selects other representers defined in the pyats\nconfiguration.  The following keys are expected to be present:\n[secrets] <prefix>.representer\n[secrets] <prefix>.key\n    '
help = 'encode a plaintext string'
name = 'encode'
run(args)

runs this subcommand

usage = '{prog} [options]'
class pyats.utils.commands.KeyGenSecret(*args, **kwargs)

Bases: pyats.cli.base.Subcommand

description = '\nGenerates a new personalized key used to encode/decode a secret string.\n\nThis key, once generated, would typically be manually placed in the pyats\nconfiguration:\n[secrets] string.key = <generated_key>\n\nThe chosen representer controls the format of the returned key.\nThe format of the returned key depends upon the representer specified\nvia the pyats configuration:\n[secrets] string.representer = representer_module.representer_class\n\nIMPORTANT: Please ensure any pyats configuration file(s) containing this key\nare locked down with appropriate permissions to ensure only authorized parties\nmay read it.\n\nIf specified, --prefix selects other representers defined in the pyats\nconfiguration.  The following key is expected to be present:\n[secrets] <prefix>.representer\n    '
help = 'generate a key used to encode/decode a secret string'
name = 'keygen'
run(args)

runs this subcommand

usage = '{prog} [options]'
class pyats.utils.commands.ValidateDatafile(*args, **kwargs)

Bases: pyats.cli.base.Subcommand

Validates that a testbed file is loadable

description = "\nValidates the provided YAML datafile for syntax and content completeness.\n\nNote:\n  This command also understands the pyATS datafile 'extends:' syntax, and\n  returns the complete, full data content with extensions fulfilled.\n    "
help = 'validate your YAML-based datafile syntax'
name = 'datafile'
run(args)

runs this subcommand

usage = '{prog} [file] [options]'
pyats.utils.commands.do_lint(yaml_file, silent=False)
pyats.utils.dicts.create_extended_dict(source_dict, dest_dict={}, rename_keys=True)

Generates a dictionary where each key is uniquely named. Duplicate keys get _1, _2, _3 etc appended to them. If exact key/value match is found, they’re excluded to avoid redundant information.

Parameters
  • source_dict (dict) – keys in this dictionary are compared against all previously seen keys

  • dest_dict (dict) – If a dest_dict is supplied, then its keys are the starting basis of previously seen keys and all key/value pairs in dest_dict will be included in the returned dict

Returns

dict - a new dictionary with uniquely named keys

Raises

N/A

pyats.utils.dicts.enforce_max_key_value_length(dict_to_check, max_key_length=40, max_value_length=512)

Enforce key length and value length rules for supplied dictionary.

Parameters
  • dict_to_check (dict) – the dictionary to check for key/value lengths

  • max_key_length (int) – maximum number of characters allowed for a key

  • max_value_length (int) – maximum number of characters allowed for a value

Returns

N/A

Raises

Exception – if any key has more characters than max_key_length or if any value has more characters than max_value_length

pyats.utils.dicts.generate_unique_key_name(key, value, dictionary, allow_match=False)str

Generates a unique key name by appending an underscore and integer

Parameters
  • key (int) – the key to make a unique name for

  • value (obj) – the value associated with the key

  • dictionary (dict) – the dictionary where the unique key will be inserted

  • allow_match (bool) – if True, allow exact key/value matches

Returns

None - if an exact key/value match was found str - if a unique key name has been generated

Raises

N/A

pyats.utils.dicts.load_dict_from_json_string(loadable)dict

Load a dictionary from a JSON string. The JSON string can optionally be urlsafe base64 encoded.

Parameters

loadable (str) – JSON string, optional with base64 encoding

Returns

dictionary

Raises

ValueError if the JSON string could not be loaded

pyats.utils.dicts.load_dict_from_kv_string(loadable)dict

load a flat dictionary from k=v value pairs.

Parameters

loadable (str) – String with k=v pairs, separated by space, optional with base64 encoding

Returns

value} pairs

Return type

dictionary of {key

pyats.utils.dicts.load_dict_from_list(loadable, unique_keys=True)dict

load a flat dictionary from string of List of string values.

Parameters
  • loadable (str) – String of List with string values, optional with base64 encoding

  • unique_keys (bool, optional) – Boolean value to convert dictionary keys to unique keys if pass as True

Returns

value} pairs

Return type

dictionary of {key

pyats.utils.dicts.recursive_cast(d, type_)

Recursively cast a nested dictionary to the provided class type

pyats.utils.dicts.recursive_setdefault(a, b)

Recursively calls setdefault on nested dictionary a with dictionary b.

pyats.utils.dicts.recursive_update(a, b, *, list_extend=False)

Recursively updates on nested dictionary a with dictionary b.

pyats.utils.dicts.set_dict_by_key_path(d, keys, val, *, append_list=False)

Utility function which sets an element in a nested dictionary by indexing the nested dictionary with a list of keys, creating any keys which don’t exist

Example

>>> d = {}
>>> set_dict_by_key_path(d, ['a', 'b', 'c'], 1)
>>> d
{'a': {'b': {'c': 1}}}
>>> set_dict_by_key_path(d, ['a', 'b', 'd'], 0)
{'a': {'b': {'c': 1, 'd': 0}}}
>>>
Parameters
  • (dictionary) (d) –

  • (list of strings) (keys) –

  • (any) (val) –

  • (bool (append_list) – append the value to it. If the element specified by the key doesnt exist, insert an empty list and append the value to it. If the existing element is not a list than raise a ValueError

  • optional) (if element specified by a key is a list,) – append the value to it. If the element specified by the key doesnt exist, insert an empty list and append the value to it. If the existing element is not a list than raise a ValueError

Returns

Return type

the value which was set, or None if no value was set

class pyats.utils.email.EmailMsg(from_email=None, to_email=None, subject='', body='', attachments=None, html_email=False, html_body='', default_domain=None)

Bases: object

EmailMsg Class

A container for email information.

EmailMsg constructor Initialize a single email message (which can be sent to multiple recipients).

Parameters
  • (list/str) (from_email) – in the generated email’s “From:” field.

  • to_email(list/str) (list or string-list of addresses to be used) – in the generated email’s “To:” field.

  • (str) (subject) –

  • (string) (html_body) –

  • (list) (attachments) –

  • (bool) (html_email) –

  • (string)

static convert_to_address(value, default_domain)

convert address values

converts space/comma/semi-colon delimited strings and lists of string ids into email address objects.

get_content()

get message body

Returns report plain text body

Returns

Return type

self.body

property mailbody

mailbody property getter

Returns the body attribute of EmailMsg object.

property mailsubject

mailsubject property getter

Returns the subject attribute of EmailMsg object.

message()

creates message

Constructs email.message.EmailMessage object

Returns

Return type

msg - email.message.EmailMessage object

recipients()

recipients list

Returns a list of all recipients of the email

Returns

Return type

self.to_email

send(host=None, port=None, ssl=None, timeout=None, username=None, password=None)

send message

Sends email using smtp host

Errors related to utils module

exception pyats.utils.exceptions.SchemaClassError(path, cls, data, detail=None, locations=None)

Bases: pyats.utils.exceptions.SchemaError

format(path, cls, data, detail, locations)
exception pyats.utils.exceptions.SchemaEmptyParserError(data)

Bases: Exception

exception pyats.utils.exceptions.SchemaError(*args, locations=None, **kwargs)

Bases: Exception

Error during Schema validation.

joinPath(path)
exception pyats.utils.exceptions.SchemaFallbackCall(path, diff_context_retry)

Bases: pyats.utils.exceptions.SchemaError

format(path, diff_context_retry)
exception pyats.utils.exceptions.SchemaFallbackError(path, data)

Bases: pyats.utils.exceptions.SchemaError

format(path, data)
exception pyats.utils.exceptions.SchemaFallbackLoopError(a, b)

Bases: pyats.utils.exceptions.SchemaError

format(a, b)
exception pyats.utils.exceptions.SchemaMissingKeyError(path, keys, locations=None)

Bases: pyats.utils.exceptions.SchemaError

format(path, keys, locations)
exception pyats.utils.exceptions.SchemaTypeError(path, schema, data, detail=None, locations=None)

Bases: pyats.utils.exceptions.SchemaError

format(path, schema, data, detail, locations)
exception pyats.utils.exceptions.SchemaUnsupportedKeyError(path, keys, locations=None)

Bases: pyats.utils.exceptions.SchemaError

format(path, keys, locations)
exception pyats.utils.exceptions.SchemaValueError(path, schema, data, detail=None, locations=None)

Bases: pyats.utils.exceptions.SchemaError

format(path, schema, data, detail, locations)
pyats.utils.exceptions.safe_chainget(d, path)
class pyats.utils.objects.Contains(value=None)

Bases: pyats.utils.objects.Operator

Contains operator

Examples

>>> class Obj():
        def __init__(self):
            self.data = {'100': {'status': 'active',
                                 'vl_mode': 'CE',
                                 'members': [1,2,3,4],
                                 'vlan_type': 'enet',
                                 'name': 'VLAN0100'}}
obj= Obj()
found = find(obj, R(['data',Operator('(.*)'), 'members', Contains(1)]))
found = find(obj, R(['data',Operator('(.*)'), 'name', Contains('100')]))

Operator class

class pyats.utils.objects.Find

Bases: object

find(from_, *requirements, type_=None, filter_=True, index=None, _first=True, all_keys=False, **kwargs)

Filters the objects that are matching the requirements in an iterable.

Params:
  • from_(list): Iterable object that will be searched. Can’t be None

  • requirements: List of requirements(R objects) for the search

  • type_(list): Class type of the object that the user wants to find,

    can be provided as a list as well

  • kwargs: Key word arguments to create a set of requirements. Easier

    for users to create requirements.

  • filter_ (bool): If True: Will return the particular matching

    object. If False: Will return the actual value which is matching. Default: True

  • index (int): Can only be used with filter_=False. Used for

    mentioning which of the dictionary value to return. Default: last element (Aka value).

  • all_keys (bool) If True: Will return all the particular matching

    objects with path to objects that matches to first requirement. If False: Will return the particular matching objects with path to objects which is matching. Default: False

Examples

>>> from pyats.utils.objects import find, R
>>> find(from_ = [1, 2, 1.2, "bla"], type_ = int)
[1, 2]
>>> find([1,2,1.2, "bla", {"bla": "blabla"}],
         R(bla = "blabla"),
         type_ = [dict])
[{"bla": "blabla"}]

TODO:

R class sets a limitation to find api’s “__” syntax, as it’s explained in the documentation, if the object name or attribute name starts or ends with “_”, find API can’t find the expected results. There are 2 ways to come over the problem, first the syntax can be something like “_r_” then limitation will be rare. Find will fail only if user object name has “_r_” in it. The other way is providing dictionaries instead of R objects as requirement sets and changing the syntax to some character that is not allowed to use as variable name such as “!” or “.”. But this will also has a limitation for dictionary keys as these characters actually allowed to be a key of a dictionary.

reset_keys()

Reset all the keys as find api returns an instance not the object.

class pyats.utils.objects.GroupKeys

Bases: object

Compose the dict which contains the headers as keys, and values

from the source corresponding keys

Short version from Genie

classmethod group_keys(source, reqs, ret_num=None, all_keys=False)

Compose the dict which contains the headers as keys, and values from the source corresponding keys

Parameters
  • source (list) – Function pyats.utils.objects.find output.

  • headers (list) – Keys from the find output, use this as headers in the table.

  • reqs (list) – List of requirements.

Returns

dict - Dictionary with the keys from args, format will be like {key1: [value1, value2], key2: [value1, value2]} empty - Empty dict

Raises

None

Example

>>> group_keys(source =                                   [('Established', ['instance', 'default',
                    'vrf', 'default', 'neighbor',
                    '200.1.1.1', 'session_state']),
                    ('Established', ['instance', 'default',
                     'vrf', 'default', 'neighbor',
                     '200:1::1:1', 'session_state'])],
               headers = ['neighbor', 'vrf', 'instance'])
>>> {'vrf': ['default', 'default'],
     'instance': ['default', 'default'],
     'neighbor': ['200.1.1.1', '200:1::1:1']}
class pyats.utils.objects.Not(value=None)

Bases: pyats.utils.objects.Operator

Not operator

Examples

>>> class Obj():
        def __init__(self):
            self.data = {'100': {'status': 'active',
                                 'vl_mode': 'CE',
                                 'members': [1,2,3,4],
                                 'vlan_type': 'enet',
                                 'name': 'VLAN0100'}}
obj= Obj()
found = find(obj, R(['data',Not('200')]))
found = find(obj, R(['data',Operator('(.*)'),
                     'status', Not('deactive')]))

Operator class

class pyats.utils.objects.NotExists(value=None)

Bases: pyats.utils.objects.Operator

Key does not exists in dictionary and object

Examples

>>> class Obj():
        def __init__(self):
            self.data = {'100': {'status': 'active',
                                 'vl_mode': 'CE',
                                 'members': [1,2,3,4],
                                 'vlan_type': 'enet',
                                 'name': 'VLAN0100'}}
obj= Obj()
found = find(obj, R(['data',Operator('(.*)'), 'members', Contains(1)]))
found = find(obj, R(['data',Operator('(.*)'), 'name', Contains('100')]))

Operator class

class pyats.utils.objects.Operator(value=None)

Bases: object

basic find operator

Takes a requirement value and uses to match laterly.

Parameters

value (object) – regex or str or any object

Examples

>>> class Obj():
        def __init__(self):
            self.data = {'100': {'status': 'active',
                                 'vl_mode': 'CE',
                                 'members': [1,2,3,4],
                                 'vlan_type': 'enet',
                                 'name': 'VLAN0100'}}
obj= Obj()
found = find(obj, R(['data',Operator('(.*)')]))
found = find(obj, R(['data',Operator('(.*)'),
                     'members', Operator([1,2,3,4])]))

Operator class

match(other)
class pyats.utils.objects.R(*args, **kwargs)

Bases: object

Requirements class

pyats.utils.objects.find(from_, *requirements, type_=None, filter_=True, index=None, _first=True, all_keys=False, **kwargs)

Filters the objects that are matching the requirements in an iterable.

Params:
  • from_(list): Iterable object that will be searched. Can’t be None

  • requirements: List of requirements(R objects) for the search

  • type_(list): Class type of the object that the user wants to find,

    can be provided as a list as well

  • kwargs: Key word arguments to create a set of requirements. Easier

    for users to create requirements.

  • filter_ (bool): If True: Will return the particular matching

    object. If False: Will return the actual value which is matching. Default: True

  • index (int): Can only be used with filter_=False. Used for

    mentioning which of the dictionary value to return. Default: last element (Aka value).

  • all_keys (bool) If True: Will return all the particular matching

    objects with path to objects that matches to first requirement. If False: Will return the particular matching objects with path to objects which is matching. Default: False

Examples

>>> from pyats.utils.objects import find, R
>>> find(from_ = [1, 2, 1.2, "bla"], type_ = int)
[1, 2]
>>> find([1,2,1.2, "bla", {"bla": "blabla"}],
         R(bla = "blabla"),
         type_ = [dict])
[{"bla": "blabla"}]

TODO:

R class sets a limitation to find api’s “__” syntax, as it’s explained in the documentation, if the object name or attribute name starts or ends with “_”, find API can’t find the expected results. There are 2 ways to come over the problem, first the syntax can be something like “_r_” then limitation will be rare. Find will fail only if user object name has “_r_” in it. The other way is providing dictionaries instead of R objects as requirement sets and changing the syntax to some character that is not allowed to use as variable name such as “!” or “.”. But this will also has a limitation for dictionary keys as these characters actually allowed to be a key of a dictionary.

class pyats.utils.parser.ArgsPropagationParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=<class 'argparse.HelpFormatter'>, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True)

Bases: argparse.ArgumentParser

parse_args(args=None, namespace=None)
class pyats.utils.parser.pyATS_HelpFormatter(*args, **kwargs)

Bases: argparse.RawTextHelpFormatter

class pyats.utils.schemaengine.And(*args, path=None)

Bases: pyats.utils.schemaengine.Schema

And Class (Schema)

Defines a schema of AND relationship, eg, the input data must pass the validation of all of the requirements of this Schema.

Example

# requires a string of ‘left’ or ‘right’ And(str, lambda: s: s in (‘left’, ‘right’))

Parameters

*args – arbitrary args of schema to apply AND to.

validate(data, top=False, locations=None, advanced_datatypes=True)

validate input

Validates the given data against the current schema, and returns the correct, validated and optionally updated data. If there are defaults or fallbacks associated with the schema, augment the input data with them so that the final return contains validated data + the defaults/fallbacks.

If advanded datatypes is enabled, returns the data with advanced datatypes, e.g. class objects instead of the original data.

Parameters
  • data (any) – data to be validated

  • advanced_datatypes (bool) – Boolean to indicate advanced datatype usage. Defaults to True

Returns

Validated data with defaults, fallbacks and advanced datatypes (optionally) applied

class pyats.utils.schemaengine.Any(path=None)

Bases: pyats.utils.schemaengine.Optional

Any Class (Optional, Schema)

Marks a section of a schema that matches anything. This is effectively a wildcard (*).

Note that Any is also Optional.

class pyats.utils.schemaengine.Default(schema, default, path=None)

Bases: pyats.utils.schemaengine.Optional

Default Class (Optional, Schema)

Defines a schema with a default. Eg, if the schema was not satisfied, the default value is added to the input data. A Default schema is also Optional.

Note

using the Default schema changes the input data (due to application of default values)

Usage Criteria:

if a Default() is part of a dictionary schema type, then keys leading to this default value cannot be marked with any other schema objects, such as Optional(). Using Default() means that its key-chain is automatically mandatory, because regardless of input, the keys leading to the default value will always be there.

Parameters
  • schema (any) – input schema requirements

  • default (any) – default value to apply

validate(data, top=False, locations=None, advanced_datatypes=True)

validate input

Validates the given data against the current schema, and returns the correct, validated and optionally updated data. If there are defaults or fallbacks associated with the schema, augment the input data with them so that the final return contains validated data + the defaults/fallbacks.

If advanded datatypes is enabled, returns the data with advanced datatypes, e.g. class objects instead of the original data.

Parameters
  • data (any) – data to be validated

  • advanced_datatypes (bool) – Boolean to indicate advanced datatype usage. Defaults to True

Returns

Validated data with defaults, fallbacks and advanced datatypes (optionally) applied

class pyats.utils.schemaengine.Fallback(schema, fallback)

Bases: pyats.utils.schemaengine.Optional

Fallback Class (Optional, Schema)

Defines a schema with a Fallback. Eg, if the schema was not satisfied, the value falls-back to another value in the given data. A Fallback schema is also Optional.

Fallbacks can only be used if the input schema and data to be validated are of type dict.

Note

using the Fallback schema changes the input data (due to application of fallback values)

Parameters
  • schema (any) – input schema requirements

  • fallback (str) – string representing the key to fallback to, using ‘.’ as separator to identify dict nesting levels.

Example

# fall back to data[‘a’][‘b’][‘c’] Fallback(str, ‘a.b.c’)

class pyats.utils.schemaengine.ListOf(schema, path=None)

Bases: pyats.utils.schemaengine.Schema

validate(data, top=False, locations=None, advanced_datatypes=True)

validate input

Validates the given data against the current schema, and returns the correct, validated and optionally updated data. If there are defaults or fallbacks associated with the schema, augment the input data with them so that the final return contains validated data + the defaults/fallbacks.

If advanded datatypes is enabled, returns the data with advanced datatypes, e.g. class objects instead of the original data.

Parameters
  • data (any) – data to be validated

  • advanced_datatypes (bool) – Boolean to indicate advanced datatype usage. Defaults to True

Returns

Validated data with defaults, fallbacks and advanced datatypes (optionally) applied

class pyats.utils.schemaengine.Optional(schema, path=None)

Bases: pyats.utils.schemaengine.Schema

Optional Class (Schema)

Marks an optional part of the schema.

class pyats.utils.schemaengine.Or(*args, path=None)

Bases: pyats.utils.schemaengine.Schema

Or Class (Schema)

Defines a schema of OR relationship, eg, the input data must pass the validation of one of the requirements of this Schema.

Example

# requires a string or an integer Or(str, int)

Parameters

*args – arbitrary args of schema to apply OR to.

validate(data, top=False, locations=None, advanced_datatypes=True)

validate input

Validates the given data against the current schema, and returns the correct, validated and optionally updated data. If there are defaults or fallbacks associated with the schema, augment the input data with them so that the final return contains validated data + the defaults/fallbacks.

If advanded datatypes is enabled, returns the data with advanced datatypes, e.g. class objects instead of the original data.

Parameters
  • data (any) – data to be validated

  • advanced_datatypes (bool) – Boolean to indicate advanced datatype usage. Defaults to True

Returns

Validated data with defaults, fallbacks and advanced datatypes (optionally) applied

class pyats.utils.schemaengine.Schema(schema, path=None)

Bases: object

Schema class

Provides the ability to define schema (schematics/requirements) for input data, and subsequently validate whether the input data meets requirements.

Example

data = Schema(str).validate(‘a string’) data = Schema({‘a’: str}).validate({‘a’: ‘some string’})

Parameters

schema – the schema to be validated against. Any valid python datastructures/callable.

apply_defaults(data)

This API takes the current data and apply default fields to it wherever needed (eg, missing fields)

Parameters

data (any) – input data

Returns

input data augmented with default values

apply_fallback(data)

This API goes through the schema looking for fallback fields. When found, it takes the fallback key, pull up its data, and apply it to the current field, if it doesn’t exist.

Parameters

data (any) – input data

Returns

input data augmented with fallback values

collect_defaults()

Based on the given schema, compute the defaults, if any. This involves using the Default subclass and creating a new datastructure that represents the default state of this schema (eg, with a None input, the resulting data should look like the output of this)

collect_fallbacks()

Based on the given schema, compute the fallbacks, if any. This involves using the Fallback subclass and creating a new datastructure that represents the fallback states of this schema, eg, if a key does not exist, it should fallback to another key’s value.

Note

Fallbacks are only valid if the schema type is Dict.

classmethod priority(obj)

Function to make sure that we always process Any objects last. Eg. process mandatory and optional ones first before trying to match Any

validate(data, top=True, locations=None, advanced_datatypes=True)

validate input

Validates the given data against the current schema, and returns the correct, validated and optionally updated data. If there are defaults or fallbacks associated with the schema, augment the input data with them so that the final return contains validated data + the defaults/fallbacks.

If advanded datatypes is enabled, returns the data with advanced datatypes, e.g. class objects instead of the original data.

Parameters
  • data (any) – data to be validated

  • advanced_datatypes (bool) – Boolean to indicate advanced datatype usage. Defaults to True

Returns

Validated data with defaults, fallbacks and advanced datatypes (optionally) applied

class pyats.utils.schemaengine.Use(schema, path=None)

Bases: pyats.utils.schemaengine.Schema

validate(data, top=False, locations=None, **kwargs)

validate input

Validates the given data against the current schema, and returns the correct, validated and optionally updated data. If there are defaults or fallbacks associated with the schema, augment the input data with them so that the final return contains validated data + the defaults/fallbacks.

If advanded datatypes is enabled, returns the data with advanced datatypes, e.g. class objects instead of the original data.

Parameters
  • data (any) – data to be validated

  • advanced_datatypes (bool) – Boolean to indicate advanced datatype usage. Defaults to True

Returns

Validated data with defaults, fallbacks and advanced datatypes (optionally) applied

class pyats.utils.secret_strings.FernetSecretStringRepresenter(obj, prefix='string')

Bases: pyats.utils.secret_strings.BaseSecretStringRepresenter

A representer for a cryptographically secure string.

decode()

Decode a contained encoded string object

encode()

Encode a contained plaintext string object

property key
classmethod keygen()

Generate a new key

class pyats.utils.secret_strings.SecretString(secret_string, representer_cls=None, prefix='string')

Bases: collections.UserString

A string that is meant to be a secret.

These strings are not displayed as plaintext but offer APIs to retrieve plaintext and also create from plaintext.

A representer:

  • Defines how the string is converted to/from plaintext.

  • If not passed in explicitly in the constructor, may be specified via the following pyats configuration value under [secrets]:

    • <prefix>.representer

  • May require a key, which may be specified via the following pyats configuration value under [secrets]:

    • <prefix>.key

  • <prefix> defaults to ‘string’ but may be overridden in the constructor with prefix, thus allowing multiple representers to be kept in the pyats configuration file.

  • Defaults to a class that implements a string that is stored using a non cryptographically secure cipher.

Initialize a new SecretString object.

If representer_cls is not specified directly, it is taken from pyats configuration if specified there.

Otherwise it defaults to a non cryptographically secure cipher.

Parameters
  • secret_string (str) – The already encoded string being modelled.

  • representer_cls (class inheriting from BaseSecretStringRepresenter) – This class handles encoding/decoding the secret string.

  • prefix (str) – The pyATS configuration prefix under the [secrets] section. The representer is specified via <prefix>.representer. The key is specified via <prefix>.key. Optional, defaults to ‘string’.

classmethod from_plaintext(plaintext, representer_cls=None, prefix='string')

Encode plaintext into a SecretString.

If the user has specified no secret string representer directly or via pyats configuration then by default a non cryptographically secure cipher is used to encode the string.

classmethod keygen(representer_cls=None, prefix='string')

Generate a key.

If the user has specified no secret string representer directly or via pyats configuration then by default a non cryptographically secure key is returned.

property plaintext

Return the plaintext equivalent of the secret string.

pyats.utils.secret_strings.to_plaintext(str_or_secret_str)

Get plaintext from a potentially secret string.

Perform any required decoding in order to return a secret string in plaintext.

pyats.utils.sig_handlers.enable_double_ctrl_c(callback=None)

This function enables the current process to quit only after 2 ctrl-c’s has been received: the first ctrl-c does nothing. Upon receiving the 2nd ctrl-c, the system will behave as expected (KeyboardInterrupt exception is raised.)

Parameters

callback (callable) – a callable function that will be called when the first ctrl-c is received. The current stack frame will be passed in as the only argument

pyats.utils.sig_handlers.restore_sigint_handler()
class pyats.utils.strings.TypeGuesser

Bases: object

Guesses string value into corresponding object types.

Supports:
  • int

  • float

  • boolean (true/false/on/off/yes/no)

  • None (none or None)

is_bool(value)
is_float(value)
is_int(value)
is_none(value)
is_type(value, type_)
to_bool(value)
pyats.utils.strings.decode_cli_string(value)

Try to decode command line string.

Parameters

value (str) – String with optional url quoted and/or base64 encoding

Returns

string

class pyats.utils.strings.force_lower_str(arg)

Bases: str

This class behaves like string, but forces itself to lowercase.

class pyats.utils.strings.force_upper_str(arg)

Bases: str

This class behaves like string, but forces itself to UPPERCASE.

pyats.utils.strings.wrap_split(str_to_wrap, sep='.', width=80)
Iterator that wraps a string across multiple lines within a given width.

Whenever possible, lines are split at a separator boundary.

str_to_wrapstr

String to wrap.

sepstr

Separator to control where the string is wrapped.

widthint

Maximum length of wrapped line.

>>> print('
‘.join(wrap_split(“one.two.three.4.5.six”,width=8)))

one.two. three.4. 5.six

>>> print('
‘.join(wrap_split(“one.two.three.4.5.six”,width=15)))

one.two.three. 4.5.six

>>> print('
‘.join(wrap_split(“one.two.three.4.5.six”,width=4)))

one. two. thre e.4. 5.

pyats.utils.utils.chainattr(obj, attrs)

Utility function, converts lists of attributes into nested obj getattr().

Example

>>> chainattr(obj, ['a','b','c'])
>>> chainattr(obj, a.b.c)
# is equivalent to
>>> obj.a.b.c
Parameters
  • (object) (obj) –

  • (list/str) (attrs) – a string, it will be split by ‘.’

Returns

Return type

the final object attribute

pyats.utils.utils.chainattrget(obj, attrkeys)

Utility function, converts list of attributes/keys into nested obj using getattr() or get().

Example

>>> chainattrget(obj, ['a','b','c'])
>>> chainattrget(obj, a.b.c)
# is equivalent to any mix of attribute or dictionary keys:
>>> obj.a.b.c
>>> obj[a][b][c]
>>> obj.a[b].c
Parameters
  • (object) (obj) –

  • (list/str) (attrkeys) – a string, it will be split by ‘.’

Returns

Return type

the final object attribute

pyats.utils.utils.chainget(d, keys)

Utility function, converts lists of keys into nested dictionary gets.

Example

>>> chainget(d, ['a','b','c'])
>>> chainget(d, 'a.b.c')
# is equivalent to
>>> d['a']['b']['c']
Parameters
  • (dict) (d) –

  • (list/str) (keys) – a string, it will be split by ‘.’

Returns

Return type

the final value

pyats.utils.utils.get_argv_args(argv)

Parse argv for dash arguments.

Arguments without a value are added as a boolean True value.

Returns

dictionary of arguments with values

pyats.utils.utils.get_distro_info()
pyats.utils.utils.get_pip_pkgs()

Get pip packages

pyats.utils.utils.get_runtime_env()
pyats.utils.utils.get_time(seconds=None)
pyats.utils.utils.get_user_frame(exclude_patterns=[])

Function that returns the desired frame, ignoring all frames related to this file and those who match any provided exclude patterns.

pyats.utils.utils.repr_data(data)

recursively explore dicts/lists and repr any non-primitives to protect pickling from weakrefs etc.

pyats.utils.utils.str_to_number(value)

Try to convert string value to float or int.

If conversion fails, return value as is.