pyats.datastructures package

Submodules

Attribute Dictionary library

This library extends python dict() data structure and enables users to access the key-values via object attributes (obj.key), in addition to obj[‘key’] style native form.

Author:

Siming Yuan (siyuan)

class pyats.datastructures.attrdict.AttrDict(*args, **kwargs)

Bases: dict

Attribute Dictionary class

The goal of the AttrDict class is to provide a Python dict() build-in var type but with the additional capability of being able to access its content as object attributes in addition to the standard manner.

Example

>>> actor = {'first': 'Arnold', 'last': 'Schwarzenegger'}
>>> actor['first']
'Arnold'
>>> import AttrDict
>>> actor = AttrDict(actor)
>>> actor.first
'Arnold'
>>> actor['first']
'Arnold'
Known Limitations:

Attributes follow the python def/variable rule, and thus dictionary keys with the special characters cannot be accessed via attribute (.) manner, such as: dot(.) comma(,) brackets() dash/hyphen(-) quotes(‘’/””) slashes(/) etc.

AttrDict object init

How this works:
  • All python objects internally store their attributes in a dictionary that is named __dict__.

  • There is no requirement that the internal dictionary __dict__ would need to be “just a plain dict”, so we can assign any subclass of dict() to the internal dictionary.

  • In our case we simply assign the AttrDict() instance we are instantiating (as we are in __init__).

  • By calling super()’s __init__() method we made sure that it (already) behaves exactly like a dictionary, since that function calls all the dictionary instantiation code.

Special Note:
  • Known to cause memory leak in Python < 2.7.3 and Python3 < 3.2.3

class pyats.datastructures.attrdict.NestedAttrDict(*args, **kwargs)

Bases: pyats.datastructures.attrdict.AttrDict, collections.abc.MutableMapping

AttrDict object init

How this works:
  • All python objects internally store their attributes in a dictionary that is named __dict__.

  • There is no requirement that the internal dictionary __dict__ would need to be “just a plain dict”, so we can assign any subclass of dict() to the internal dictionary.

  • In our case we simply assign the AttrDict() instance we are instantiating (as we are in __init__).

  • By calling super()’s __init__() method we made sure that it (already) behaves exactly like a dictionary, since that function calls all the dictionary instantiation code.

Special Note:
  • Known to cause memory leak in Python < 2.7.3 and Python3 < 3.2.3

get(k[, d]) D[k] if k in D, else d.  d defaults to None.
pop(k[, d]) v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

setdefault(k[, d]) D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) None.  Update D from dict/iterable E and F.

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

class pyats.datastructures.classproperty.ClassPropertyDescriptor(func)

Bases: object

descriptor class, allowing classes to have its own “properties” that can be overwritten, enherited, etc. Adds read-only classproperty functionality to Python. This is intended to be used as a decorator

Example

class MyClass(object):

@classproperty def someclassproperty(cls):

return 100

Credit to: http://stackoverflow.com/questions/5189699/how-to-make-a-class-property

pyats.datastructures.classproperty.classproperty

alias of pyats.datastructures.classproperty.ClassPropertyDescriptor

class pyats.datastructures.configuration.Configuration(*args, **kwargs)

Bases: pyats.datastructures.attrdict.NestedAttrDict

AttrDict object init

How this works:
  • All python objects internally store their attributes in a dictionary that is named __dict__.

  • There is no requirement that the internal dictionary __dict__ would need to be “just a plain dict”, so we can assign any subclass of dict() to the internal dictionary.

  • In our case we simply assign the AttrDict() instance we are instantiating (as we are in __init__).

  • By calling super()’s __init__() method we made sure that it (already) behaves exactly like a dictionary, since that function calls all the dictionary instantiation code.

Special Note:
  • Known to cause memory leak in Python < 2.7.3 and Python3 < 3.2.3

copy()

slightly differ from the standard Mapping.copy() api - this always takes a nested object copy if it encounters another Configuration block underneath.

This is done to ensure configuration doesn’t get corrupted when a subcomponent takes a copy and updates it for its own use.

load_cfgs(*files)
load_entrypoint(group)

populate this configuration by loading an entrypoint.

The design of this API is so that we can scatter configuration in different packages and load them when needed and if installed.

Note that this requires the entrypoint to be a dict/Configuration like object. It would be good practise for each module owner, if they have a lot of configuration, to have their own local config.cfg file and load it as part of the entrypoint module .

load_yamls(*files)
class pyats.datastructures.factory.MetaClassFactory

Bases: type

MetaClassFactory Metaclass

Enabling a class to be dynamically changed to another subclass during instanciation, if argument ‘class’ is provided. Typically, this allows dynamic class loading through YAML files (or other similar datafiles), and replaces classes during runtime without having to explictly write a lot of if/else code. (This is kind of like class overloading)

Notes

  • this only works if the provided class is a subclass of the original class

  • the provided argument ‘class’ is removed from the list of arguments and not passed down to the actual class object

  • kwargs must be used to provide class argument, because class is a reserved keyword. MyClass(class=SubClass) doesn’t work because of that, and this is a desired behavior. Ideally, this class factory is only invoked at the loading layer and not from a user’s script.

Example

>>> class MyClass(metaclass = MetaClassFactory):
...     pass
>>> class SubClass(MyClass):
...     pass
>>> kwargs = {'class': SubClass}
>>> assert MyClass(**kwargs) is SubClass
>>> MyClass(class=SubClass)
                ^
SyntaxError: invalid syntax
class pyats.datastructures.listdict.DictItem(path, value)

Bases: tuple

Create new instance of DictItem(path, value)

path

Alias for field number 0

value

Alias for field number 1

class pyats.datastructures.listdict.IndexMarker(obj, index)

Bases: object

Tracks the index position of elements in list/tuple

obj: obj to store for index: index value

class pyats.datastructures.listdict.ListDict(*args)

Bases: list

ListDict class (list)

Provides a “flattened” representation of nested dictionaries. The idea behind this data structure is to represent nested dictionaries using a path-value concept, where the path represents the dictionary key nesting, and the value is the object stored at the end:

dictionary[‘a’][‘b’][‘c’] = object()

is now equivalent to

((‘a’, ‘b’, ‘c’,), object())

This class provides the forward and backward translation of nested dict to a list/tuple form. This eliminates the need to write recursive functions for handling dictionary nesting, as it converts a nested 2D tree structure to a single dimentional list.

This class extends the base Python list class.

Example:

dictionary = {
    'a': {
        'b': {
            'c': {
                'd': object(),
                'e': object(),
            }
        }
    }
}
list_form = ListDict(dictionary)
[(('a', 'b', 'c', 'd'), object()),
 (('a', 'b', 'c', 'e'), object()),]
Format:

breaks down a dictionary into the format of: [(path, value), (path, value) …]

where path is a tuple representing the nested dict keys.

Note

This class represents a transformation and reconstruction of a nested dictionary, and thus the yielded object (dict) is not the same as the input dict.

assert ListDict({}).reconstruct() == {} assert ListDict({}).reconstruct() is not {}

built-in __init__

Parameters
  • *args – any arguments accepted by list() is also accepted.

  • condition (special) – if the input is a dictionary, then the dictionary will be flattened to be stored internally as a list structure.

append(item)

Appends a new path/value to this list.

Parameters
  • index (int) – list index to insert to

  • item (path/value) – tuple of path/obj to append

extend(items)

Extends the object with many new path/values.

Parameters
  • index (int) – list index to insert to

  • items (list of path/value) – list of tuple of path/obj to insert

insert(index, item)

Inserts a new path/value to this list.

Parameters
  • index (int) – list index to insert to

  • item (path/value) – tuple of path/obj to insert

reconstruct()

Reconstruct

Takes the current internally stored list-form dictionary and reconstruct it into its represented dictionary format. Note that this always generates a new dictionary object.

Returns

dictionary object.

class pyats.datastructures.logic.And(*expressions)

Bases: pyats.datastructures.logic.BaseLogic

Logical And

Logical And testing, True when all expressions are satisfied, False otherwise.

If a list of items are tested against And logic, And returns True as long as each And’ed expression tests true against one of the list items.

built-in __init__

Instanciate class with a list of expressions (checks) from the user. These expressions/checks will be used as part of the api __call__ to validate input information.

If an expression is given in the form of a string, it is compiled into a regex search function.

Parameters

(str/callable) (expressions) –

class pyats.datastructures.logic.Not(*expressions)

Bases: pyats.datastructures.logic.BaseLogic

Logical Not

Logical Not testing, True when all expressions are not satisfied, False when all expressions are not satisfied.

If a list of items is tested against Not logic, Not returns True only when all items tests False.

built-in __init__

Instanciate class with a list of expressions (checks) from the user. These expressions/checks will be used as part of the api __call__ to validate input information.

If an expression is given in the form of a string, it is compiled into a regex search function.

Parameters

(str/callable) (expressions) –

class pyats.datastructures.logic.Or(*expressions)

Bases: pyats.datastructures.logic.BaseLogic

Logical Or

Logical Or testing, True when one or more expressions are satisfied, False when all expressions are not satisfied.

If a list of items are tested against Or logic, Or returns True as long as one of Or’ed expression tests true against one of the list items.

built-in __init__

Instanciate class with a list of expressions (checks) from the user. These expressions/checks will be used as part of the api __call__ to validate input information.

If an expression is given in the form of a string, it is compiled into a regex search function.

Parameters

(str/callable) (expressions) –

class pyats.datastructures.orderabledict.OrderableDict(*args, **kwargs)

Bases: collections.abc.MutableMapping

A subclass of MutableMapping (similar to dict) that remembers the order that keys were first inserted (similar to collections.OrderedDict), but also allows the user to move keys orders around (which OrderedDict does not support) using the OrderableDict.move() method.

Note

inefficient implementaion. dictionary keys are duplicated internally and stored in order to save key insertion order. if you have lots of key/value entries and your keys are large, it may eat up more memory (relatively speaking) than raw dict.

clear() None.  Remove all items from D.
copy()
classmethod fromkeys(keys, value=None)
insert(key, value, position)

inserts a new key-value pair to a given position.

Parameters
  • (str) (key) –

  • (obj) (value) –

  • (int) (position) –

Examples

>>> obj = OrderableDict([('a',1), ('b', 2), ('c', 3)])
>>> obj.insert('d', 4, 1)
>>> obj
OrderableDict([('c', 3), ('d', 4), ('a', 1), ('b', 2)])
items() a set-like object providing a view on D's items
keys() a set-like object providing a view on D's keys
move(key, position)

moves a known key within the dictionary into another position using index values.

Parameters
  • (str) (key) –

  • (int) (position) –

Examples

>>> obj = OrderableDict([('a',1), ('b', 2), ('c', 3)])
>>> obj.move('c', 0)
>>> obj
OrderableDict([('c', 3), ('a', 1), ('b', 2)])
update([E, ]**F) None.  Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() an object providing a view on D's values
class pyats.datastructures.treenode.TreeNode(name, children=None)

Bases: object

Tree Tree Class

A class to mimic the printing behavior of linux tree command.

Example:

root = TreeNode('grandmother')
daughter = TreeNode('daughter', [TreeNode('granddaughterA'),
                                 TreeNode('grandsonB')])
son = TreeNode('son', [TreeNode('granddaughterB'),
                       TreeNode('grandsonB')])
son.add_child(TreeNode('granddaughterC',
                       [TreeNode('grandgranddaughterA'),
                        TreeNode('grandgrandsonA')]))
son.add_child(TreeNode('granddaughterD',
                       [TreeNode('grandgranddaughterB'),
                        TreeNode('grandgrandsonB')]))
root.add_child(daughter)
root.add_child(son)
print(str(root))

Output:

grandmother
|-- daughter
|   |-- granddaughterA
|   `-- grandsonB
`-- son
    |-- granddaughterB
    |-- grandsonB
    |-- granddaughterC
    |   |-- grandgranddaughterA
    |   `-- grandgrandsonA
    `-- granddaughterD
        |-- grandgranddaughterB
        `-- grandgrandsonB

class __init__

Parameters
  • name (str) – name of TreeNode

  • children (list) – list of children TreeNodes

add_child(item)

Add children

adds a children TreeNode to this TreeNode

Parameters

item (TreeNode) – children node to add

class pyats.datastructures.weaklist.WeakList(items=())

Bases: collections.UserList

WeakList Class

A special implementation of python native list object, where the stored items are weak references of the original list.

Special Behaviors:
  • if an object referenced is finalized (garbage collected), its reference is removed from the list automatically (auto-cleanup)

  • all queries (read) from the list returns the actual object.

  • all modifications (writes) to the list takes in actual objects, and stores in the form of weakrefs.

  • all handling of weakrefs should be invisible to the user.

Note

Because all stored items are weakrefs, be careful of context and garbage collections.

append(item)

S.append(value) – append value to the end of the sequence

count(value) integer -- return number of occurrences of value
extend(items)

S.extend(iterable) – extend sequence by appending elements from the iterable

index(value[, start[, stop]]) integer -- return first index of value.

Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

insert(index, item)

S.insert(index, value) – insert value before index

pop([index]) item -- remove and return item at index (default last).

Raise IndexError if list is empty or index is out of range.

remove(item)

S.remove(value) – remove first occurrence of value. Raise ValueError if the value is not present.

sort(key=None, reverse=False)