Parse whitespace-based network configuration into a tree of parent/child relationships.
Project description
networkconfparse
networkconfparse is a library that parses the whitespace-indented configuration of network infrastructure (Cisco IOS, IOS XE, IOS XR, and NX-OS) into a queryable tree of native Python objects.
Why networkconfparse?
- Standalone - No runtime dependencies. Install and use it in any Python project.
- Network-OS agnostic - Hierarchy is inferred from relative indentation, so IOS (one space), NX-OS (two spaces), and inconsistent indentation are all handled without per-platform rules.
- Queryable - A small, composable API to find configuration objects by regex, by predicate, or by their parent/child relationships.
- Handles the awkward parts - Transparently skips
!comment and delimiter lines and captures multilinebannerblocks and inline certificate data as opaque bodies, rather than mistaking them for configuration. - Typed and well-tested - Fully type-hinted with a comprehensive test suite.
Installation
networkconfparse can be quickly and easily installed with uv as shown below:
uv add networkconfparse
Or, if you prefer good old-fashioned pip, you can do so as shown below:
pip install networkconfparse
Quick Examples
Parsing a Configuration
Call parse() with the configuration text. It returns a Config whose top-level lines each carry their indented children as a tree of ConfigNode objects. Comment/delimiter lines (!) are dropped automatically.
import networkconfparse
config = networkconfparse.parse("""
interface GigabitEthernet0/0
ip address 10.0.0.1 255.255.255.0
no shutdown
!
interface GigabitEthernet0/1
shutdown
!
""")
for interface in config.find(r"^interface "):
print(interface.text, "->", [child.text for child in interface.children])
Prints:
interface GigabitEthernet0/0 -> ['ip address 10.0.0.1 255.255.255.0', 'no shutdown']
interface GigabitEthernet0/1 -> ['shutdown']
Querying the Tree
find() searches the entire tree and accepts a regular expression, a where predicate, or both. find_child()/has_child() look only at a node's immediate children, and find_one() returns the first match. Every node also exposes path, ancestors, descendants, and root for navigation.
# Interfaces that have an IP address configured anywhere beneath them.
configured = config.find(r"^interface ", where=lambda node: node.has_child(r"^ip address "))
# The first matching line, or None.
mgmt = config.find_one(r"^ip address 10\.0\.0\.1")
# Where does that line live in the hierarchy?
print(mgmt.path)
# ['interface GigabitEthernet0/0', 'ip address 10.0.0.1 255.255.255.0']
Relationship Helpers
For the common cases, dedicated helpers read more clearly than a hand-written predicate. Each accepts a single regex or a list (combined with AND), and they are simply convenience wrappers around find():
# Parents matching "interface" that have BOTH children as direct children.
config.find_with_child(r"^interface ", [r"^ip address ", r"^no shutdown"])
# Parents that have a matching line anywhere below them (not just direct children).
config.find_with_descendant(r"^router bgp ", r"neighbor")
# Lines whose direct parent matches.
config.find_with_parent(r"^neighbor ", r"^address-family ipv4")
# Lines with a matching ancestor anywhere above (or a consecutive chain with adjacent=True).
config.find_with_ancestor(r"^neighbor ", [r"^router bgp ", r"^address-family ipv4"])
Each helper has a find_without_* counterpart for the equally common absence questions ("interfaces without an ip address"). Given a list they apply a "none present" (NOR) rule, returning nodes where none of the patterns are found:
# Interfaces with neither an `ip address` nor a `shutdown` line.
config.find_without_child(r"^interface ", [r"^ip address ", r"^shutdown"])
These compose naturally for SDK-style questions. For example, "find every ACL that does not end with an explicit deny":
acls = config.find(r"^ip access-list ")
missing_deny = [
acl for acl in acls
if not acl.children or not acl.children[-1].matches(r"^deny ")
]
Documentation
Full documentation is available at chartinolabs.github.io/networkconfparse.
- Changelog - Release history built from changelog fragments
- Changelog Fragments Guide - How to add release-note fragments
- Releasing - How to compile release notes and cut a release
Acknowledgments
- Conceptual inspiration - The idea of modeling a network device configuration as a queryable parent/child tree owes a great deal to Mike Pennington's work on CiscoConfParse and CiscoConfParse2. networkconfparse is an independent, clean-room implementation; it is not affiliated with, derived from, or endorsed by those projects.
Status
Early development. The API is still evolving and may change as the library matures.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file networkconfparse-0.2.0.tar.gz.
File metadata
- Download URL: networkconfparse-0.2.0.tar.gz
- Upload date:
- Size: 87.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b90f62194cbf01671a067a1992d57a52c210bb830e50d75c50b3be4a2c28915
|
|
| MD5 |
56872db4bdc0764be94d491d58e4ff67
|
|
| BLAKE2b-256 |
032af197856a9154dd05da634dd79d0a0df6deec0ad5739e6c591f4167aa3c41
|
Provenance
The following attestation bundles were made for networkconfparse-0.2.0.tar.gz:
Publisher:
release.yaml on ChartinoLabs/networkconfparse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
networkconfparse-0.2.0.tar.gz -
Subject digest:
3b90f62194cbf01671a067a1992d57a52c210bb830e50d75c50b3be4a2c28915 - Sigstore transparency entry: 1976192776
- Sigstore integration time:
-
Permalink:
ChartinoLabs/networkconfparse@75fd3feebadcceccc9414658d4d5aabd1625378d -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ChartinoLabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@75fd3feebadcceccc9414658d4d5aabd1625378d -
Trigger Event:
push
-
Statement type:
File details
Details for the file networkconfparse-0.2.0-py3-none-any.whl.
File metadata
- Download URL: networkconfparse-0.2.0-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
433bd36ea82e9e7a6587e96f002e7511e1c8009f0c1e452f777c7587382d076d
|
|
| MD5 |
33cec3325a5293e049dbb226729d36ba
|
|
| BLAKE2b-256 |
a06700c701008e04dbfd522608cac8d218a00684a833059a8583e939067400c6
|
Provenance
The following attestation bundles were made for networkconfparse-0.2.0-py3-none-any.whl:
Publisher:
release.yaml on ChartinoLabs/networkconfparse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
networkconfparse-0.2.0-py3-none-any.whl -
Subject digest:
433bd36ea82e9e7a6587e96f002e7511e1c8009f0c1e452f777c7587382d076d - Sigstore transparency entry: 1976192870
- Sigstore integration time:
-
Permalink:
ChartinoLabs/networkconfparse@75fd3feebadcceccc9414658d4d5aabd1625378d -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ChartinoLabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@75fd3feebadcceccc9414658d4d5aabd1625378d -
Trigger Event:
push
-
Statement type: