Skip to content

API Reference

Load a template and parse the provided data string with TTP.

path argument is always preferred over other arguments.

Valid combinations of template location arguments:

  • path="./misc/foo/bar.txt"
  • platform="cisco_ios", command="show version"
  • yang="ietf-interfaces", platform="cisco_ios"
  • misc="foo_folder/bar_template.txt"
  • get="inventory", platform="cisco_xr"

Parameters:

Name Type Description Default
data str

Raw text data to parse.

required
path Optional[str]

OS path or ttp:// URI to the template file to load.

None
platform Optional[str]

Platform name to load the template for, e.g. cisco_ios. Required when get is used — it selects the platform-specific input inside the getter template (e.g. "cisco_xr", "arista_eos").

None
command Optional[str]

CLI command to load the template for, e.g. show ip arp.

None
yang Optional[str]

YANG module name to load the template for, e.g. ietf-interfaces.

None
misc Optional[str]

Path to the template relative to the repository misc folder.

None
get Optional[str]

Name of the getter template, e.g. "inventory". Works similarly to NAPALM getters — a single getter bundles platform-specific parsing logic and returns a normalized, platform-agnostic structure. platform must also be supplied so the correct input section is selected.

None
structure Optional[str]

Output structure format - list, dictionary, or flat_list.

'list'
template_vars Optional[Dict]

Additional variables to pass into the TTP template object.

None

Returns:

Type Description
Union[Dict, List]

Parsed results as a dict or list, depending on the structure argument.

Raises:

Type Description
ValueError

If no valid template-locating argument combination is provided, or if get is used without platform.

RuntimeError

If get is used and none of the getter's inputs support the specified platform.

Source code in ttp_templates\ttp_templates.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def parse_output(
    data: str,
    platform: Optional[str] = None,
    command: Optional[str] = None,
    path: Optional[str] = None,
    yang: Optional[str] = None,
    misc: Optional[str] = None,
    get: Optional[str] = None,
    structure: Optional[str] = "list",
    template_vars: Optional[Dict] = None,
) -> Union[Dict, List]:
    """Load a template and parse the provided data string with TTP.

    ``path`` argument is always preferred over other arguments.

    Valid combinations of template location arguments:

    * ``path="./misc/foo/bar.txt"``
    * ``platform="cisco_ios", command="show version"``
    * ``yang="ietf-interfaces", platform="cisco_ios"``
    * ``misc="foo_folder/bar_template.txt"``
    * ``get="inventory", platform="cisco_xr"``

    Args:
        data: Raw text data to parse.
        path: OS path or ``ttp://`` URI to the template file to load.
        platform: Platform name to load the template for, e.g. ``cisco_ios``.
            **Required** when ``get`` is used — it selects the platform-specific
            input inside the getter template (e.g. ``"cisco_xr"``, ``"arista_eos"``).
        command: CLI command to load the template for, e.g. ``show ip arp``.
        yang: YANG module name to load the template for, e.g. ``ietf-interfaces``.
        misc: Path to the template relative to the repository ``misc`` folder.
        get: Name of the getter template, e.g. ``"inventory"``. Works similarly to
            NAPALM getters — a single getter bundles platform-specific parsing logic
            and returns a normalized, platform-agnostic structure. ``platform`` must
            also be supplied so the correct input section is selected.
        structure: Output structure format - ``list``, ``dictionary``, or
            ``flat_list``.
        template_vars: Additional variables to pass into the TTP template object.

    Returns:
        Parsed results as a dict or list, depending on the ``structure`` argument.

    Raises:
        ValueError: If no valid template-locating argument combination is provided,
            or if ``get`` is used without ``platform``.
        RuntimeError: If ``get`` is used and none of the getter's inputs support
            the specified ``platform``.
    """
    template_vars = template_vars or {}

    log.debug(
        "parse_output: loading template (platform=%r, command=%r, "
        "path=%r, yang=%r, misc=%r)",
        platform,
        command,
        path,
        yang,
        misc,
    )

    # retrieve the template text using the provided locator arguments
    template = get_template(
        platform=platform, command=command, path=path, yang=yang, misc=misc, get=get
    )

    if template is None:
        raise ValueError(
            "parse_output: no valid template-locating argument combination was "
            "provided; supply one of: path, platform+command, yang+platform, or misc."
        )

    log.debug("parse_output: creating TTP parser, structure=%r", structure)

    # handle getter if platform is given
    if get:
        if not platform:
            raise ValueError(
                f"'{get}' getter need platform name to parse provided data"
            )
        parser = ttp(template=template, vars=template_vars)
        # sort input data across inputs
        input_found = False
        for template_name, inputs in parser.get_input_load().items():
            for input_name, params in inputs.items():
                if platform in params.get("platform", []):
                    parser.add_input(
                        template_name=template_name, input_name=input_name, data=data
                    )
                    input_found = True
                    break
            if input_found:
                break
        else:
            raise RuntimeError(
                f"None of the '{get}' getter inputs support platform '{platform}'"
            )
        # parse the data and return result only for template with matched input
        parser.parse(one=True)
        results = parser.result(structure="dictionary")
        results = results[template_name]
    else:
        # parse the data
        parser = ttp(data=data, template=template, vars=template_vars)
        parser.parse(one=True)
        results = parser.result(structure=structure)

    log.debug("parse_output: parsing complete")
    return results

Locate a template file and return its content.

path argument is always preferred over other arguments.

Valid combinations of template location arguments:

  • path="./misc/foo/bar.txt"
  • platform="cisco_ios", command="show version"
  • yang="ietf-interfaces", platform="cisco_ios"
  • misc="foo_folder/bar_template.txt"
  • get="foo_folder/bar_template.txt"

Parameters:

Name Type Description Default
path Optional[str]

OS path or ttp:// URI to the template file to load.

None
platform Optional[str]

Platform name to load the template for, e.g. cisco_ios.

None
command Optional[str]

CLI command to load the template for, e.g. show ip arp.

None
yang Optional[str]

YANG module name to load the template for, e.g. ietf-interfaces.

None
misc Optional[str]

Path to the template relative to the repository misc folder.

None
get Optional[str]

Name of the getter template e.g. "inventory"

None

Returns:

Type Description
Optional[str]

Template file content as a string, or None if no valid argument

Optional[str]

combination was provided.

Source code in ttp_templates\ttp_templates.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def get_template(
    path: Optional[str] = None,
    platform: Optional[str] = None,
    command: Optional[str] = None,
    yang: Optional[str] = None,
    misc: Optional[str] = None,
    get: Optional[str] = None,
) -> Optional[str]:
    """Locate a template file and return its content.

    ``path`` argument is always preferred over other arguments.

    Valid combinations of template location arguments:

    * ``path="./misc/foo/bar.txt"``
    * ``platform="cisco_ios", command="show version"``
    * ``yang="ietf-interfaces", platform="cisco_ios"``
    * ``misc="foo_folder/bar_template.txt"``
    * ``get="foo_folder/bar_template.txt"``

    Args:
        path: OS path or ``ttp://`` URI to the template file to load.
        platform: Platform name to load the template for, e.g. ``cisco_ios``.
        command: CLI command to load the template for, e.g. ``show ip arp``.
        yang: YANG module name to load the template for, e.g. ``ietf-interfaces``.
        misc: Path to the template relative to the repository ``misc`` folder.
        get: Name of the getter template e.g. "inventory"

    Returns:
        Template file content as a string, or ``None`` if no valid argument
        combination was provided.
    """
    # resolve the relative path to the template file based on provided arguments
    if path:
        # strip the optional "ttp://" scheme prefix used by TTP library
        if path.strip().startswith("ttp://"):
            path = path.strip()[6:]
        log.debug("get_template: using explicit path '%s'", path)
    elif get:
        path = (
            "get/{}".format(get) if get.endswith(".txt") else "get/{}.txt".format(get)
        )
        log.debug("get_template: resolved get path '%s'", path)
    elif platform and command:
        platform = platform.lower()
        command = command.lower()
        # replace pipe symbol with the word "pipe" to form a valid filename
        command = command.replace("|", "pipe")
        # quotes may group multi-word CLI arguments but are not part of filenames
        command = command.replace('"', "").replace("'", "")
        for symbol in [" ", "-"]:
            platform = platform.replace(symbol, "_")
            command = command.replace(symbol, "_")
        path = "platform/{}_{}.txt".format(platform, command)
        log.debug("get_template: resolved platform+command path '%s'", path)
    elif platform and yang:
        platform = platform.lower()
        yang = yang.lower()
        for symbol in [" "]:
            platform = platform.replace(symbol, "_")
            yang = yang.replace(symbol, "_")
        path = "yang/{}_{}.txt".format(yang, platform)
        log.debug("get_template: resolved yang+platform path '%s'", path)
    elif misc:
        path = "misc/{}".format(misc)
        log.debug("get_template: resolved misc path '%s'", path)
    else:
        log.warning(
            "get_template: no valid argument combination provided, " "returning None"
        )
        return None

    template_dir = os.path.abspath(os.path.dirname(__file__))
    # Resolve symlinks and ".." segments so the containment check is reliable
    template_filename = os.path.realpath(os.path.join(template_dir, path))

    # Ensure the resolved path stays inside the package directory to prevent
    # path-traversal attacks (e.g. path="../../etc/passwd").
    if not template_filename.startswith(template_dir + os.sep):
        raise ValueError(
            f"Template path '{path}' resolves outside the package directory."
        )

    log.debug("get_template: loading template file '%s'", template_filename)

    # read and return the template file content
    with open(template_filename, mode="r", encoding="utf-8") as f:
        content = f.read()

    log.debug(
        "get_template: loaded template '%s', %d characters",
        template_filename,
        len(content),
    )
    return content

Return platform names and aliases supported by a getter template.

The check uses the platform metadata declared in getter input blocks, the same metadata used by :func:parse_output to route getter parsing.

Parameters:

Name Type Description Default
getter str

Getter template name, e.g. "interfaces" or "bgp_asn". The .txt extension is optional.

required

Returns:

Type Description
List[str]

Sorted list of platform names and aliases, or an empty list if the

List[str]

getter template does not exist.

Source code in ttp_templates\ttp_templates.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
def list_getter_platforms(getter: str) -> List[str]:
    """Return platform names and aliases supported by a getter template.

    The check uses the platform metadata declared in getter input blocks, the
    same metadata used by :func:`parse_output` to route getter parsing.

    Args:
        getter: Getter template name, e.g. ``"interfaces"`` or ``"bgp_asn"``.
            The ``.txt`` extension is optional.

    Returns:
        Sorted list of platform names and aliases, or an empty list if the
        getter template does not exist.
    """
    try:
        template = get_template(get=getter)
    except FileNotFoundError:
        log.debug("list_getter_platforms: getter '%s' was not found", getter)
        return []

    parser = ttp(template=template)
    platforms = set()
    for inputs in parser.get_input_load().values():
        for params in inputs.values():
            platforms.update(params.get("platform", []))

    log.debug(
        "list_getter_platforms: getter '%s' supports platforms %s",
        getter,
        sorted(platforms),
    )
    return sorted(platforms)

Return whether a getter template supports a platform.

Parameters:

Name Type Description Default
platform str

Platform name or alias to check, e.g. "linux".

required
getter str

Getter template name, e.g. "interfaces" or "bgp_asn". The .txt extension is optional.

required

Returns:

Type Description
bool

True if the getter exists and one of its inputs lists the platform,

bool

otherwise False.

Source code in ttp_templates\ttp_templates.py
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
def is_getter_supported(
    platform: str,
    getter: str,
) -> bool:
    """Return whether a getter template supports a platform.

    Args:
        platform: Platform name or alias to check, e.g. ``"linux"``.
        getter: Getter template name, e.g. ``"interfaces"`` or ``"bgp_asn"``.
            The ``.txt`` extension is optional.

    Returns:
        ``True`` if the getter exists and one of its inputs lists the platform,
        otherwise ``False``.
    """
    if platform in list_getter_platforms(getter):
        log.debug(
            "is_getter_supported: getter '%s' supports platform '%s'",
            getter,
            platform,
        )
        return True

    log.debug(
        "is_getter_supported: getter '%s' does not support platform '%s'",
        getter,
        platform,
    )
    return False

List available templates whose filenames match the given glob pattern.

The primary use case for this function is to simplify integration with other applications by providing a programmatic API to enumerate all available TTP templates.

Parameters:

Name Type Description Default
pattern str

Glob pattern used to filter template filenames. Defaults to "*" which matches all templates.

'*'

Returns:

Type Description
Dict

Dictionary with three top-level keys:

Dict
  • platform - list of matching platform template filenames.
Dict
  • yang - list of matching YANG template filenames.
Dict
  • misc - nested dict mirroring the misc/ directory hierarchy, with leaf values being lists of matching filenames.
Source code in ttp_templates\ttp_templates.py
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
def list_templates(pattern: str = "*") -> Dict:
    """List available templates whose filenames match the given glob pattern.

    The primary use case for this function is to simplify integration with
    other applications by providing a programmatic API to enumerate all
    available TTP templates.

    Args:
        pattern: Glob pattern used to filter template filenames. Defaults to
            ``"*"`` which matches all templates.

    Returns:
        Dictionary with three top-level keys:

        * ``platform`` - list of matching platform template filenames.
        * ``yang`` - list of matching YANG template filenames.
        * ``misc`` - nested dict mirroring the ``misc/`` directory hierarchy,
            with leaf values being lists of matching filenames.
    """
    res: Dict = {
        "platform": [],
        "yang": [],
        "misc": {},
        "get": [],
    }
    # filenames to exclude regardless of the caller's pattern
    skip_files = ["readme.md"]
    paths = ["platform", "yang", "misc", "get"]
    ttp_templates_dir = os.path.abspath(os.path.dirname(__file__))

    log.debug(
        "list_templates: scanning '%s' with pattern '%s'", ttp_templates_dir, pattern
    )

    for path in paths:
        dirname = os.path.join(ttp_templates_dir, path)
        for dirpath, dirnames, filenames in os.walk(dirname):
            # build a list of folder names relative to the package root
            # e.g. "/platform" → ["platform"], "/misc/N2G/cli_ip_data" → ["misc", "N2G", "cli_ip_data"]
            dirpath_items = dirpath.replace(ttp_templates_dir, "").split(os.sep)[1:]

            # skip directories that contain no files
            if not filenames:
                continue

            # keep only files that match the caller's glob pattern and are not in the skip list;
            # sort the result so the output is deterministic regardless of filesystem ordering
            files = sorted(
                filename
                for filename in filenames
                if (
                    fnmatchcase(filename, pattern)
                    and filename.lower() not in skip_files
                )
            )

            # traverse the result dict to the correct nesting level and store the file list
            ref = res
            for index, item in enumerate(dirpath_items):
                if index + 1 == len(dirpath_items):
                    # Reached the leaf directory: store the matching files list.
                    # Guard against overwriting an existing sub-dict, which would
                    # happen if a template file sits directly inside misc/ alongside
                    # subdirectories (e.g. misc/my_template.txt).  In that case we
                    # store the files under the empty-string key so the dict
                    # structure is preserved and subsequent iterations don't crash.
                    if isinstance(ref.get(item), dict):
                        ref[item][""] = files
                    else:
                        ref[item] = files
                else:
                    # descend one level deeper, creating intermediate dicts as needed
                    ref = ref.setdefault(item, {})

    log.debug("list_templates: scan complete")
    return res

Return a flat list of ttp:// references for all matching templates.

Each entry uses the ttp:// URI scheme understood by :func:get_template e.g.:

  • ttp://platform/cisco_ios_show_ip_arp.txt
  • ttp://misc/N2G/cli_ip_data/cisco_ios.txt

Parameters:

Name Type Description Default
pattern str

Glob pattern used to filter template filenames.

'*'

Returns:

Type Description
list

Sorted list of ttp:// URI strings for all matching templates.

Source code in ttp_templates\ttp_templates.py
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
def list_templates_refs(pattern: str = "*") -> list:
    """Return a flat list of ``ttp://`` references for all matching templates.

    Each entry uses the ``ttp://`` URI scheme understood by :func:`get_template`  e.g.:

    * ``ttp://platform/cisco_ios_show_ip_arp.txt``
    * ``ttp://misc/N2G/cli_ip_data/cisco_ios.txt``

    Args:
        pattern: Glob pattern used to filter template filenames.

    Returns:
        Sorted list of ``ttp://`` URI strings for all matching templates.
    """
    skip_files = ["readme.md"]
    paths = ["platform", "yang", "misc", "get"]
    ttp_templates_dir = os.path.abspath(os.path.dirname(__file__))
    refs: list = []

    for path in paths:
        dirname = os.path.join(ttp_templates_dir, path)
        for dirpath, _dirnames, filenames in os.walk(dirname):
            # path relative to the package root, using forward slashes for the URI
            rel_dir = os.path.relpath(dirpath, ttp_templates_dir).replace(os.sep, "/")
            for filename in filenames:
                if (
                    fnmatchcase(filename, pattern)
                    and filename.lower() not in skip_files
                ):
                    refs.append("ttp://{}/{}".format(rel_dir, filename))

    log.debug("list_templates_refs: found %d refs", len(refs))
    return sorted(refs)