Skip to main content

A Python library for parsing and comparing hierarchical network device configurations

Project description

Network Configuration Parser

A Python library for parsing and analyzing hierarchical network device configurations with space-based indentation.

Features

  • Parse network configurations from files or strings
  • Build hierarchical parent-child relationships based on indentation
  • Rich metadata for each configuration line (level, children, siblings, etc.)
  • Search configurations with flexible filters
  • Compare configurations to identify differences
  • Support for any device with space-based indentation (Cisco, Arista, etc.)

Installation

From PyPI (Recommended)

pip install netconf-parser

From Source

git clone https://github.com/w4hf/netconf-parser.git
cd netconf-parser
pip install -e .

For Development

git clone https://github.com/w4hf/netconf-parser.git
cd netconf-parser
pip install -e ".[dev]"

Quick Start

Basic Usage

from netconf_parser import Conf

# Load from a string
config_text = """hostname router1
interface GigabitEthernet0/1
 ip address 192.168.1.1 255.255.255.0
 no shutdown
 description WAN Link
"""

conf = Conf.from_string(config_text)

# Or load from a file
conf = Conf.from_file("config.txt")

# Access all lines
print(f"Total lines: {len(conf.lines)}")

# Access root-level lines
for line in conf.root_lines:
    print(f"Root line: {line}")

Working with ConfLine Objects

Each line in the configuration is represented by a ConfLine object with rich metadata:

# Get a line
line = conf.lines[1]  # interface line

# Access properties
print(f"Content: {line.content}")  # ['interface', 'GigabitEthernet0/1']
print(f"Line number: {line.line_num}")
print(f"Level: {line.level}")
print(f"Has children: {line.has_children}")
print(f"Has parent: {line.has_parent}")
print(f"Is lone line: {line.lone_line}")

# Access relationships
print(f"Direct children: {line.direct_children_count}")
print(f"All descendants: {line.all_children_count}")

# Iterate through children
for child in line.children:
    print(f"  Child: {child}")

# Check siblings
for sibling in line.siblings:
    print(f"  Sibling: {sibling}")

Searching Configurations

Use search_line_start_with() to find specific lines:

from netconf_parser import search_line_start_with

# Find all interface lines at level 0
interfaces = search_line_start_with(conf, "interface", level=0)

# Find IP address lines under interfaces
ip_addresses = search_line_start_with(
    conf, 
    "ip address", 
    level=1, 
    parent_start_with="interface"
)

# Find descriptions under a specific interface
descriptions = search_line_start_with(
    conf,
    "description",
    level=1,
    parent_start_with="interface GigabitEthernet0/1"
)

Comparing Configurations

Compare two configurations to identify differences:

from netconf_parser import compare_confs

# Load two configurations
ref_conf = Conf.from_file("baseline.txt")
new_conf = Conf.from_file("current.txt")

# Compare them
deleted, added, modified_root, modified_children = compare_confs(
    ref_conf, 
    new_conf,
    ignore_regex=r"^!"  # Ignore comment lines
)

# Check deleted lines
print("Deleted lines:")
for line in deleted:
    print(f"  - {line}")

# Check added lines
print("Added lines:")
for line in added:
    print(f"  + {line}")

# Check modified root lines
print("Modified root lines:")
for line in modified_root:
    print(f"  ~ {line}")

# Check modified children
print("Modified children:")
for group in modified_children:
    print(f"  Group with parent: {group[0].parent}")
    for line in group:
        print(f"    ~ {line}")

API Reference

Classes

Conf

Represents a complete network configuration.

Class Methods:

  • from_string(config_text: str) -> Conf: Create from a multiline string
  • from_file(file_path: str) -> Conf: Create from a file

Properties:

  • lines: List of all ConfLine objects
  • root_lines: List of root-level ConfLine objects (level 0)

ConfLine

Represents a single configuration line with hierarchical properties.

Properties:

  • content: List of keywords (whitespace removed)
  • line_num: Line number in the configuration
  • level: Indentation depth (0 = root)
  • has_children: Boolean indicating if line has children
  • has_parent: Boolean indicating if line has a parent
  • parent: Reference to parent ConfLine (or None)
  • children: List of direct child ConfLine objects
  • siblings: List of sibling ConfLine objects
  • lone_line: True if line has no parent or children
  • direct_children_count: Number of direct children
  • all_children_count: Total number of descendants
  • direct_children: List of direct children's content
  • all_children: List of all descendants' content

Functions

search_line_start_with()

Search for configuration lines matching specific criteria.

search_line_start_with(
    conf: Conf,
    search_string: str,
    level: int,
    parent_start_with: str | None = None
) -> list[ConfLine]

Parameters:

  • conf: The Conf object to search
  • search_string: String that lines must start with
  • level: The indentation level to match
  • parent_start_with: Optional filter for parent line content

Returns: List of matching ConfLine objects

compare_confs()

Compare two configurations and identify differences.

compare_confs(
    reference_conf: Conf,
    compared_conf: Conf,
    ignore_regex: str = ""
) -> tuple[list[ConfLine], list[ConfLine], list[ConfLine], list[list[ConfLine]]]

Parameters:

  • reference_conf: The baseline configuration
  • compared_conf: The configuration to compare
  • ignore_regex: Regular expression for lines to ignore

Returns: A tuple containing:

  1. deleted_lines: Lines in reference but not in compared
  2. added_lines: Lines in compared but not in reference
  3. modified_root_lines: Root lines with same start but different content
  4. modified_children: Groups of child lines with modifications

Running Tests

pytest tests/

To run with verbose output:

pytest -v tests/

To run a specific test file:

pytest tests/test_parser.py

Requirements

  • Python 3.12+
  • pytest 8.0+ (for testing)

License

This project is provided as-is for parsing network device configurations.

Examples

Example 1: Analyzing Interface Configuration

from netconf_parser import Conf, search_line_start_with

config = """
interface GigabitEthernet0/1
 description WAN Link
 ip address 192.168.1.1 255.255.255.0
 no shutdown
interface GigabitEthernet0/2
 description LAN Link
 ip address 10.0.0.1 255.255.255.0
 shutdown
"""

conf = Conf.from_string(config)

# Find all interfaces with "shutdown" configured
for interface in conf.root_lines:
    if interface.content[0] == "interface":
        has_no_shutdown = any(
            " ".join(child.content) == "no shutdown" 
            for child in interface.children
        )
        has_shutdown = any(
            " ".join(child.content) == "shutdown" 
            for child in interface.children
        )
        
        if has_shutdown and not has_no_shutdown:
            print(f"Interface {interface.content[1]} is shutdown")

Example 2: Configuration Audit

from netconf_parser import Conf

config = """
interface GigabitEthernet0/1
 ip address 192.168.1.1 255.255.255.0
interface GigabitEthernet0/2
 ip address 10.0.0.1 255.255.255.0
 description Configured
interface GigabitEthernet0/3
 ip address 172.16.0.1 255.255.255.0
"""

conf = Conf.from_string(config)

# Find interfaces without descriptions
print("Interfaces without descriptions:")
for line in conf.root_lines:
    if line.content[0] == "interface":
        has_description = any(
            child.content[0] == "description" 
            for child in line.children
        )
        if not has_description:
            print(f"  - {line.content[1]}")

Example 3: Configuration Diff Report

from netconf_parser import Conf, compare_confs

old_config = """hostname old-router
interface GigabitEthernet0/1
 ip address 192.168.1.1 255.255.255.0"""

new_config = """hostname new-router
interface GigabitEthernet0/1
 ip address 192.168.1.2 255.255.255.0"""

old_conf = Conf.from_string(old_config)
new_conf = Conf.from_string(new_config)

deleted, added, modified_root, modified_children = compare_confs(old_conf, new_conf)

print("Configuration Changes Report")
print("=" * 50)
print(f"Deleted lines: {len(deleted)}")
print(f"Added lines: {len(added)}")
print(f"Modified root lines: {len(modified_root)}")
print(f"Modified child groups: {len(modified_children)}")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

netconf_parser-1.0.0.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

netconf_parser-1.0.0-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

Details for the file netconf_parser-1.0.0.tar.gz.

File metadata

  • Download URL: netconf_parser-1.0.0.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for netconf_parser-1.0.0.tar.gz
Algorithm Hash digest
SHA256 ea59916e0937a2baf724fa3f8ece699c3cd1acbb3d035901f34bfea6df9452bd
MD5 87eb665617f518ed9ce4254f3366c02a
BLAKE2b-256 8d495f21bde8c0caad7d460c752eddfe7ee84d7e54221679121ddce12237ce9c

See more details on using hashes here.

File details

Details for the file netconf_parser-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: netconf_parser-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 10.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for netconf_parser-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9edee4a29944250d1a9421533f040ad6967dfe7bd798c52e8bc4bbd44887c02e
MD5 87ca8ca4ccb0b173b84c4787f392864e
BLAKE2b-256 2eb8888947949b4ae3b13f28a1debdcdead083d686457fd5641f3b912aa400d5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page