Skip to content

helper

scrapli.helper

format_user_warning(title: str, message: str) -> str

Nicely format a warning message for users

Parameters:

Name Type Description Default
title str

title of the warning message

required
message str

actual message body

required

Returns:

Name Type Description
str str

nicely formatted warning

Source code in scrapli/helper.py
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def format_user_warning(title: str, message: str) -> str:
    """
    Nicely format a warning message for users

    Args:
        title: title of the warning message
        message: actual message body

    Returns:
        str: nicely formatted warning

    Raises:
        N/A

    """
    terminal_width = get_terminal_size().columns
    warning_banner_char = "*"

    if len(title) > (terminal_width - 4):
        warning_header = warning_banner_char * terminal_width
    else:
        banner_char_count = terminal_width - len(title) - 2
        left_banner_char_count = banner_char_count // 2
        right_banner_char_count = (
            banner_char_count / 2 if banner_char_count % 2 == 0 else (banner_char_count // 2) + 1
        )
        warning_header = (
            f"{warning_banner_char:{warning_banner_char}>{left_banner_char_count}}"
            f" {title} "
            f"{warning_banner_char:{warning_banner_char}<{right_banner_char_count}}"
        )

    warning_footer = warning_banner_char * terminal_width

    return (
        "\n\n"
        + warning_header
        + "\n"
        + message.center(terminal_width)
        + "\n"
        + warning_footer
        + "\n"
    )

genie_parse(platform: str, command: str, output: str) -> Union[List[Any], Dict[str, Any]]

Parse output with Cisco genie parsers, try to return structured output

Parameters:

Name Type Description Default
platform str

genie device type; i.e. iosxe, iosxr, etc.

required
command str

string of command that was executed (to find appropriate parser)

required
output str

unstructured output from device to parse

required

Returns:

Name Type Description
output Union[List[Any], Dict[str, Any]]

structured data

Source code in scrapli/helper.py
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
def genie_parse(platform: str, command: str, output: str) -> Union[List[Any], Dict[str, Any]]:
    """
    Parse output with Cisco genie parsers, try to return structured output

    Args:
        platform: genie device type; i.e. iosxe, iosxr, etc.
        command: string of command that was executed (to find appropriate parser)
        output: unstructured output from device to parse

    Returns:
        output: structured data

    Raises:
        N/A

    """
    try:
        Device = getattr(importlib.import_module(name=".conf.base", package="genie"), "Device")
        get_parser = getattr(
            importlib.import_module(name=".libs.parser.utils", package="genie"), "get_parser"
        )
    except ModuleNotFoundError as exc:
        title = "Optional Extra Not Installed!"
        message = (
            "Optional extra 'genie' is not installed!\n"
            f"To resolve this issue, install '{exc.name}'. You can do this in one of the following"
            " ways:\n"
            "1: 'pip install -r requirements-genie.txt'\n"
            "2: 'pip install scrapli[genie]'"
        )
        user_warning(title=title, message=message)
        return []

    genie_device = Device("scrapli_device", custom={"abstraction": {"order": ["os"]}}, os=platform)

    try:
        get_parser(command, genie_device)
        genie_parsed_result = genie_device.parse(command, output=output)
        if isinstance(genie_parsed_result, (list, dict)):
            return genie_parsed_result
    except Exception as exc:  # pylint: disable=W0703
        logger.warning(f"failed to parse data with genie, genie raised exception: `{exc}`")
    return []

resolve_file(file: str) -> str

Resolve file from provided string

Parameters:

Name Type Description Default
file str

string path to file

required

Returns:

Name Type Description
str str

string path to file

Raises:

Type Description
ScrapliValueError

if file cannot be resolved

Source code in scrapli/helper.py
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
def resolve_file(file: str) -> str:
    """
    Resolve file from provided string

    Args:
        file: string path to file

    Returns:
        str: string path to file

    Raises:
        ScrapliValueError: if file cannot be resolved

    """
    if Path(file).is_file():
        return str(Path(file))
    if Path(file).expanduser().is_file():
        return str(Path(file).expanduser())
    raise ScrapliValueError(f"File path `{file}` could not be resolved")

textfsm_parse(template: Union[str, TextIOWrapper], output: str, to_dict: bool = True) -> Union[List[Any], Dict[str, Any]]

Parse output with TextFSM and ntc-templates, try to return structured output

Parameters:

Name Type Description Default
template Union[str, TextIOWrapper]

TextIOWrapper or string of URL or filesystem path to template to use to parse data

required
output str

unstructured output from device to parse

required
to_dict bool

convert textfsm output from list of lists to list of dicts -- basically create dict from header and row data so it is easier to read/parse the output

True

Returns:

Name Type Description
output Union[List[Any], Dict[str, Any]]

structured data

Source code in scrapli/helper.py
 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def textfsm_parse(
    template: Union[str, TextIOWrapper], output: str, to_dict: bool = True
) -> Union[List[Any], Dict[str, Any]]:
    """
    Parse output with TextFSM and ntc-templates, try to return structured output

    Args:
        template: TextIOWrapper or string of URL or filesystem path to template to use to parse data
        output: unstructured output from device to parse
        to_dict: convert textfsm output from list of lists to list of dicts -- basically create dict
            from header and row data so it is easier to read/parse the output

    Returns:
        output: structured data

    Raises:
        N/A

    """
    import textfsm  # pylint: disable=C0415

    if not isinstance(template, TextIOWrapper):
        if template.startswith("http://") or template.startswith("https://"):
            with urllib.request.urlopen(template) as response:
                template_file = TextIOWrapper(
                    BytesIO(response.read()),
                    encoding=response.headers.get_content_charset(),
                )
        else:
            template_file = TextIOWrapper(open(template, mode="rb"))  # pylint: disable=R1732
    else:
        template_file = template
    re_table = textfsm.TextFSM(template_file)
    try:
        structured_output: Union[List[Any], Dict[str, Any]] = re_table.ParseText(output)
        if to_dict:
            structured_output = _textfsm_to_dict(
                structured_output=structured_output, header=re_table.header
            )
        return structured_output
    except textfsm.parser.TextFSMError:
        logger.warning("failed to parse data with textfsm")
    return []

ttp_parse(template: Union[str, TextIOWrapper], output: str) -> Union[List[Any], Dict[str, Any]]

Parse output with TTP, try to return structured output

Parameters:

Name Type Description Default
template Union[str, TextIOWrapper]

TextIOWrapper or string path to template to use to parse data

required
output str

unstructured output from device to parse

required

Returns:

Name Type Description
output Union[List[Any], Dict[str, Any]]

structured data

Source code in scrapli/helper.py
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
def ttp_parse(template: Union[str, TextIOWrapper], output: str) -> Union[List[Any], Dict[str, Any]]:
    """
    Parse output with TTP, try to return structured output

    Args:
        template: TextIOWrapper or string path to template to use to parse data
        output: unstructured output from device to parse

    Returns:
        output: structured data

    Raises:
        N/A

    """
    try:
        ttp = getattr(importlib.import_module(name="ttp"), "ttp")
    except ModuleNotFoundError as exc:
        title = "Optional Extra Not Installed!"
        message = (
            "Optional extra 'ttp' is not installed!\n"
            f"To resolve this issue, install '{exc.name}'. You can do this in one of the following"
            " ways:\n"
            "1: 'pip install -r requirements-ttp.txt'\n"
            "2: 'pip install scrapli[ttp]'"
        )
        user_warning(title=title, message=message)
        return []

    if not isinstance(template, (str, TextIOWrapper)):
        logger.info(f"invalid template `{template}`; template should be string or TextIOWrapper")
        return []

    ttp_parser_template_name = "scrapli_ttp_parse"
    ttp_parser = ttp()
    ttp_parser.add_template(template=template, template_name=ttp_parser_template_name)
    ttp_parser.add_input(data=output, template_name=ttp_parser_template_name)
    ttp_parser.parse()
    ttp_result: Dict[str, List[Any]] = ttp_parser.result(structure="dictionary")
    return ttp_result[ttp_parser_template_name]

user_warning(title: str, message: str) -> None

Nicely raise warning messages for users

Parameters:

Name Type Description Default
title str

title of the warning message

required
message str

actual message body

required

Returns:

Type Description
None

None

Source code in scrapli/helper.py
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
def user_warning(title: str, message: str) -> None:
    """
    Nicely raise warning messages for users

    Args:
        title: title of the warning message
        message: actual message body

    Returns:
        None

    Raises:
        N/A

    """
    warning_message = format_user_warning(title=title, message=message)
    logger.warning(warning_message)

    if Settings.SUPPRESS_USER_WARNINGS is False:
        warn(warning_message)