Translator

class yangify.translator.RootTranslator(dm: yangson.datamodel.DataModel, candidate: Dict[str, Any], running: Optional[Dict[str, Any]] = None, replace: bool = False)

This object represents the root of the translator and allows the user to choose which parts of the model to translate and with which translators. To do so assign the parser classes to class attributes named after the nodes you want to translate.

Parameters:
  • dm – DataModel we are going to be translating
  • candidate – This is the data of the object we are translating
  • running – This is set when merging one object into another. Pretty much like TranslatorData.candidate, but with the running data.
  • replace – Whether we are merging candidate into running or replacing it entirely.

Examples

Parsing both openconfig-interfaces and openconfig-vlan models:

from yangify import parser

class Interfaces(parser.Parser):
    ...

class Vlans(parser.Parser):
    ...

class Parser(parser.RootParser):
    interfaces = Interfaces
    vlans = Vlans

Parsing only openconfig-interfaces but using a different parser:

from yangify import parser

class InterfacesAlt(parser.Parser):
    ...

class Parser(parser.RootParser):
    interfaces = InterfacesAlt
process() → Any
class yangify.translator.Translator(result: Any, root_result: Any, path: yangson.instance.InstanceRoute, dm: yangson.datamodel.DataModel, schema: yangson.schemanode.DataNode, keys: Dict[str, str], candidate: yangson.instance.ObjectMember, running: Optional[yangson.instance.ObjectMember], replace: bool)

Translator classes used to parse groupings need to inherit from this class. In addition to the relevant functions and classes to translate children nodes, they may include a Yangify class that inherits from TranslatorData to implement some parsing logic.

yy

This attribute will be instantiated using the nested class Translator.Yangify. Everything you implement inside your class Yangify will be available through this attribute.

Type:TranslatorData

Example

Interface class to parse openconfig-interfaces:interfaces/interface model:

class Interface(Parser):
    class Yangify(ParserData):
        def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]:
            for k, v in interfaces_magic:
                yield k, v
Yangify

alias of TranslatorData

class yangify.translator.TranslatorData(result: Any, root_result: Any, path: yangson.instance.InstanceRoute, schema: yangson.schemanode.DataNode, keys: Dict[str, Any], candidate: yangson.instance.ObjectMember, running: Optional[yangson.instance.ObjectMember], replace: bool)

This is the base class for the Translator.Yangify object.

result

Exact details will depend on the translator implementation but the general idea is that the translator will set it to the most convenient object possible.

Type:Any
root_result

Exact details will depend on the translator but this object should always point to the root of resulting translation.

Type:Any
path

This attribute will hold the path to nearest grouping. For leaves it means it will point to the parent container, for lists to exact element being processed for containers to the container itself.

Type:yangson.instance.InstanceRoute
schema

This is the schema for the current node.

Type:yangson.schemanode.DataNode
keys

This dictionary keeps track of all the keys relevant to the current object being processed. Keys are equal to the path where the key was extracted while the value is the actual value. For instance, if you were translating the interface FastEthernet1.1 using the openconfig:interfaces model, you’d have the following keys:

{
    "openconfig-interfaces:interfaces/interface": "FastEthernet1",
    "openconfig-interfaces:interfaces/interface/subinterfaces/subinterface": 1,
}
Type:Dict[str, Any]
candidate

This is the object we are translating, it always always to the root of it. It can be combined with the TranslatorData.path to go to parts of it. For instance:

self.candidate.goto(self.path[:-2]).raw_values()

Should point you two steps above your current position and then give you the raw value of it (a dictionary most likely)

Type:yangson.instance.RootNode
running

This is set when merging one object into another. Pretty much like TranslatorData.candidate, but with the running data.

Type:Optional[`yangson.instance.RootNode]
replace

This is set to True when performing a replace operation.

Type:bool
to_remove

When processing YANG lists and performing either a merge or replace operation, this List will be populated with the elements that need to be removed.

Type:List[yangson.instance.ObjectMember]
init() → None

Called only by the RootTranslator in the very beginning of the processing. This function may be used to preprocess the result object or for anything else that may be needed to do before the actual processing starts.

key

Last key extracted in the current object being processed.

metadata = {}
path = ''
post() → None

Called only by the RootTranslator in the very end of the processing.

post_process() → None

This is called after processing either a container or a list element.

post_process_list() → None

This is called after processing a list.

pre_process() → None

This is called before processing either a container or a list element.

pre_process_list() → None

This is called before processing a list.

yangify.translator.unneeded(*args, **kwargs) → None

You can use this dummy function to flag that a particular leaf doesn’t need to be processed. Otherwise, the system will flag it as not implemented.

Example

we don’t need to vlan_id as it’s the same as the key:

class VlanConfig(Translator):
    def name(self):
        ...

    vlan_id = unneeded
class yangify.translator.config_tree.ConfigTree(header: Optional[str] = None)

ConfigTree is an object that helps you recreate a hierarchical config like:

interface Gi1
   description "A description for Gi1"
   shutdown
   exit
!
interface Gi2
   description "A description for Gi2"
   exit
!
logging something something
logging something else

Headers represent the begining of the section, i.e., Interface Gi1 and Interface Gi2 in our example above (empty for the root object), while commands are commands within that section. For instance, to recreate the object above you’d do:

>>> config = ConfigTree()
>>> gi1 = config.new_section("interface Gi1")
>>> gi1.add_command("   description "A description for Gi1"")
>>> gi1.add_command("   shutdown")
>>> gi1.add_command("   exit")
>>> gi1.add_command("!")
>>> gi2 = config.new_section("interface Gi2")
>>> gi2.add_command("   description "A description for Gi2"")
>>> gi2.add_command("   exit")
>>> gi2.add_command("!")
>>> config.add_command("logging something something")
>>> config.add_command("logging something else")
add_command(child: str) → None

Adds a command to the current object

new_section(header: str) → yangify.translator.config_tree.ConfigTree

Create a new section and return it.

pop_section(header: str) → yangify.translator.config_tree.ConfigTree

Remove a section from the current object.

to_string() → str

Convert object to a string