Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-ciscoconfparse for
openSUSE:Factory checked in at 2022-10-29 20:16:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ciscoconfparse (Old)
and /work/SRC/openSUSE:Factory/.python-ciscoconfparse.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ciscoconfparse"
Sat Oct 29 20:16:49 2022 rev:25 rq:1032073 version:1.6.50
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-ciscoconfparse/python-ciscoconfparse.changes
2022-10-21 16:20:14.742251416 +0200
+++
/work/SRC/openSUSE:Factory/.python-ciscoconfparse.new.2275/python-ciscoconfparse.changes
2022-10-29 20:18:05.490525468 +0200
@@ -1,0 +2,22 @@
+Thu Oct 27 22:29:08 UTC 2022 - Yogalakshmi Arunachalam <[email protected]>
+
+- Update to version 1.6.50:
+ Released: 2022-10-21
+ Summary:
+ * Modify .github/workflows/tests.yml with improved yml
+ * Enhance CiscoConfParse().repr() string output
+ * Minor package documentation tweaks
+
+- Update to version 1.6.49:
+ * Adjust string strip() conditions on config lines in
assign_parent_to_closing_braces()
+
+- Update to version 1.6.48:
+ * Add code to catch misconfigurations such as parsing a string instead of a
list in ciscoconfparse.ConfigList(``)
+ * Avoid problems with reading empty lines (see Github Issue #251)
+
+- Update to version 1.6.47:
+ * Add repo version management into the Makefile ('make bump-version-patch' /
'make bump-version-minor')
+ * Add repo version management to 'dev_tools/git_helper.py'
+ * Revise README_git_workflow.md to include more rebase and merge details
+
+-------------------------------------------------------------------
Old:
----
ciscoconfparse-1.6.41.tar.gz
New:
----
ciscoconfparse-1.6.50.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-ciscoconfparse.spec ++++++
--- /var/tmp/diff_new_pack.dKY79w/_old 2022-10-29 20:18:05.986528111 +0200
+++ /var/tmp/diff_new_pack.dKY79w/_new 2022-10-29 20:18:05.994528153 +0200
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%bcond_without python2
Name: python-ciscoconfparse
-Version: 1.6.41
+Version: 1.6.50
Release: 0
Summary: Library for parsing, querying and modifying Cisco IOS-style
configurations
License: GPL-3.0-or-later
++++++ ciscoconfparse-1.6.41.tar.gz -> ciscoconfparse-1.6.50.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ciscoconfparse-1.6.41/PKG-INFO
new/ciscoconfparse-1.6.50/PKG-INFO
--- old/ciscoconfparse-1.6.41/PKG-INFO 2022-09-10 00:29:24.075619200 +0200
+++ new/ciscoconfparse-1.6.50/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: ciscoconfparse
-Version: 1.6.41
+Version: 1.6.50
Summary: Parse, Audit, Query, Build, and Modify Cisco IOS-style and
JunOS-style configurations
Home-page: https://github.com/mpenning/ciscoconfparse
License: GPLv3
@@ -21,11 +21,12 @@
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Communications
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -152,7 +153,7 @@
Pre-requisites
--------------
-[The ciscoconfparse python package][3] requires Python versions 3.6+ (note:
Python version 3.7.0 has a bug - ref [Github issue \#117][18], but version
3.7.1 works); the OS should not matter.
+[The ciscoconfparse python package][3] requires Python versions 3.7+ (note:
Python version 3.7.0 has a bug - ref [Github issue \#117][18], but version
3.7.1 works); the OS should not matter.
Installation and Downloads
--------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ciscoconfparse-1.6.41/README.md
new/ciscoconfparse-1.6.50/README.md
--- old/ciscoconfparse-1.6.41/README.md 2022-05-26 11:47:08.097129000 +0200
+++ new/ciscoconfparse-1.6.50/README.md 2022-10-20 13:10:54.100284000 +0200
@@ -112,7 +112,7 @@
Pre-requisites
--------------
-[The ciscoconfparse python package][3] requires Python versions 3.6+ (note:
Python version 3.7.0 has a bug - ref [Github issue \#117][18], but version
3.7.1 works); the OS should not matter.
+[The ciscoconfparse python package][3] requires Python versions 3.7+ (note:
Python version 3.7.0 has a bug - ref [Github issue \#117][18], but version
3.7.1 works); the OS should not matter.
Installation and Downloads
--------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ciscoconfparse-1.6.41/ciscoconfparse/ccp_abc.py
new/ciscoconfparse-1.6.50/ciscoconfparse/ccp_abc.py
--- old/ciscoconfparse-1.6.41/ciscoconfparse/ccp_abc.py 2022-07-20
02:06:20.741461800 +0200
+++ new/ciscoconfparse-1.6.50/ciscoconfparse/ccp_abc.py 2022-10-20
13:10:54.100284000 +0200
@@ -18,7 +18,6 @@
"""
from difflib import get_close_matches
-from operator import methodcaller
from abc import ABCMeta
import warnings
import inspect
@@ -538,10 +537,8 @@
!
>>>
"""
- cobjs = filter(methodcaller("re_search", linespec), self.children)
- retval = [ii.text for ii in cobjs]
- # Delete the children
- map(methodcaller("delete"), cobjs)
+ # if / else in a list comprehension... ref --->
https://stackoverflow.com/a/9442777/667301
+ retval = [(obj.delete() if obj.re_search(linespec) else obj) for obj
in self.children]
return retval
# On BaseCfgLine()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ciscoconfparse-1.6.41/ciscoconfparse/ccp_util.py
new/ciscoconfparse-1.6.50/ciscoconfparse/ccp_util.py
--- old/ciscoconfparse-1.6.41/ciscoconfparse/ccp_util.py 2022-09-10
00:25:02.491401000 +0200
+++ new/ciscoconfparse-1.6.50/ciscoconfparse/ccp_util.py 2022-10-20
13:10:54.100284000 +0200
@@ -143,7 +143,7 @@
"""
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def __init__(self):
self.PYTHONOPTIMIZE_env_value = os.environ.get("PYTHONOPTIMIZE", None)
@@ -178,8 +178,136 @@
if error != "__no_error__":
raise PythonOptimizeException(error)
[email protected](reraise=True)
+def ccp_logger_control(
+ sink=sys.stderr,
+ action="",
+ handler_id=None,
+ allow_enqueue=True,
+ # rotation="00:00",
+ # retention="1 month",
+ # compression="zip",
+ level="DEBUG",
+ colorize=True,
+ debug=0,
+):
+ """
+ A simple function to handle logging... Enable / Disable all
+ ciscoconfparse logging here... also see Github issue #211.
+
+ Example
+ -------
+ """
+
+ msg = "ccp_logger_control() was called with sink='{}', action='{}',
handler_id='{}', allow_enqueue={}, level='{}', colorize={}, debug={}".format(
+ sink,
+ action,
+ handler_id,
+ allow_enqueue,
+ # rotation,
+ # retention,
+ # compression,
+ level,
+ colorize,
+ debug,
+ )
+ if debug > 0:
+ logger.info(msg)
+
+ assert isinstance(action, str)
+ assert action in ("remove", "add", "disable", "enable", "",)
+
+ package_name = "ciscoconfparse"
+
+ if action == "remove":
+ # Require an explicit loguru handler_id to remove...
+ assert isinstance(handler_id, int)
+
+ logger.remove(handler_id)
+ return True
+
+ elif action == "disable":
+ # Administratively disable this loguru logger
+ logger.disable(package_name)
+ return True
+
+ elif action == "enable":
+ # Administratively enable this loguru logger
+ logger.enable(package_name)
+ return True
+
+ elif action == "add":
+
+ logger.add(
+ sink=sink,
+ diagnose=True,
+ backtrace=True,
+ # https://github.com/mpenning/ciscoconfparse/issues/215
+ enqueue=allow_enqueue,
+ serialize=False,
+ catch=True,
+ # rotation="00:00",
+ # retention="1 day",
+ # compression="zip",
+ colorize=True,
+ level="DEBUG",
+ )
+ logger.enable(package_name)
+ return True
+
+ elif action == "":
+ raise ValueError(
+ "action='' is not supported. Please use a valid action keyword"
+ )
+
+ else:
+ raise NotImplementedError(
+ "action='%s' is an unsupported logger action" % action
+ )
+
+
[email protected](reraise=True)
+def configure_loguru(
+ sink=sys.stderr,
+ action="",
+ # rotation="midnight",
+ # retention="1 month",
+ # compression="zip",
+ level="DEBUG",
+ colorize=True,
+ debug=0,
+):
+ """
+ configure_loguru()
+ """
+ assert isinstance(action, str)
+ assert action in ('remove', 'add', 'enable', 'disable', '',)
+ # assert isinstance(rotation, str)
+ # assert isinstance(retention, str)
+ # assert isinstance(compression, str)
+ # assert compression == "zip"
+ assert isinstance(level, str)
+ assert isinstance(colorize, bool)
+ assert isinstance(debug, int) and (0 <= debug <= 5)
+
+ # logger_control() was imported above...
+ # Remove the default loguru logger to stderr (handler_id==0)...
+ ccp_logger_control(action="remove", handler_id=0)
+
+ # Add log to STDOUT
+ ccp_logger_control(
+ sink=sys.stdout,
+ action="add",
+ level="DEBUG",
+ # rotation='midnight', # ALE barks about the rotation keyword...
+ # retention="1 month",
+ # compression=compression,
+ colorize=colorize
+ )
+ ccp_logger_control(action="enable")
+
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def as_text_list(object_list):
"""
This is a helper-function to convert a list of configuration objects into
@@ -217,11 +345,11 @@
return list(map(attrgetter("text"), object_list))
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def junos_unsupported(func):
"""A function wrapper to warn junos users of unsupported features"""
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def wrapper(*args, **kwargs):
warn = "syntax='junos' does not fully support config modifications
such as .{}(); see Github Issue #185.
https://github.com/mpenning/ciscoconfparse/issues/185".format(
func.__name__
@@ -240,7 +368,7 @@
return wrapper
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def log_function_call(function=None, *args, **kwargs):
"""A wrapper; this decorator uses loguru to log function calls.
@@ -253,7 +381,7 @@
"""
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def logging_decorator(ff):
@wraps(ff)
def wrapped_logging(*args, **kwargs):
@@ -283,93 +411,6 @@
return logging_decorator
[email protected](default=True, onerror=lambda _: sys.exit(1))
-def ccp_logger_control(
- sink=sys.stderr,
- action="",
- handler_id=None,
- allow_enqueue=True,
- # rotation="00:00",
- # retention="1 month",
- # compression="zip",
- level="DEBUG",
- colorize=True,
- debug=0,
-):
- """
- A simple function to handle logging... Enable / Disable all
- ciscoconfparse logging here... also see Github issue #211.
-
- Example
- -------
- """
-
- msg = "ccp_logger_control() was called with sink='{}', action='{}',
handler_id='{}', allow_enqueue={}, level='{}', colorize={}, debug={}".format(
- sink,
- action,
- handler_id,
- allow_enqueue,
- # rotation,
- # retention,
- # compression,
- level,
- colorize,
- debug,
- )
- if debug > 0:
- logger.info(msg)
-
- assert isinstance(action, str)
- assert action in ("remove", "add", "disable", "enable", "",)
-
- package_name = "ciscoconfparse"
-
- if action == "remove":
- # Require an explicit loguru handler_id to remove...
- assert isinstance(handler_id, int)
-
- logger.remove(handler_id)
- return True
-
- elif action == "disable":
- # Administratively disable this loguru logger
- logger.disable(package_name)
- return True
-
- elif action == "enable":
- # Administratively enable this loguru logger
- logger.enable(package_name)
- return True
-
- elif action == "add":
-
- logger.add(
- sink=sink,
- diagnose=True,
- backtrace=True,
- # https://github.com/mpenning/ciscoconfparse/issues/215
- enqueue=allow_enqueue,
- serialize=False,
- catch=True,
- # rotation="00:00",
- # retention="1 day",
- # compression="zip",
- colorize=True,
- level="DEBUG",
- )
- logger.enable(package_name)
- return True
-
- elif action == "":
- raise ValueError(
- "action='' is not supported. Please use a valid action keyword"
- )
-
- else:
- raise NotImplementedError(
- "action='%s' is an unsupported logger action" % action
- )
-
class __ccp_re__(object):
"""
@@ -402,7 +443,7 @@
"""
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def __init__(self, regex_str=r"", target_str=None, groups=None, flags=0,
debug=0):
assert isinstance(regex_str, str)
@@ -628,7 +669,7 @@
error_str = "Cannot parse '%s' as ipv4 or ipv6" % val
raise AddressValueError(error_str)
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def collapse_addresses(network_list):
"""
This is a ciscoconfparse proxy for ipaddress.collapse_addresses()
@@ -642,7 +683,7 @@
"""
assert isinstance(network_list, list) or isinstance(network_list, tuple)
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def ip_net(arg):
if isinstance(arg, IPv4Obj):
return arg.network
@@ -2242,7 +2283,7 @@
)
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def dns_query(input_str="", query_type="", server="", timeout=2.0):
"""A unified IPv4 & IPv6 DNS lookup interface; this is essentially just a
wrapper around dnspython's API. When you query a PTR record, you can use an
IPv4 or IPv6 address (which will automatically be converted into an
in-addr.arpa name. This wrapper only supports a subset of DNS records: 'A',
'AAAA', 'CNAME', 'MX', 'NS', 'PTR', and 'TXT'
@@ -2435,7 +2476,7 @@
return retval
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def dns_lookup(input_str, timeout=3, server="", record_type="A"):
"""Perform a simple DNS lookup, return results in a dictionary"""
rr = Resolver()
@@ -2475,7 +2516,7 @@
}
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def dns6_lookup(input_str, timeout=3, server=""):
"""Perform a simple DNS lookup, return results in a dictionary"""
rr = Resolver()
@@ -2500,7 +2541,7 @@
_REVERSE_DNS_REGEX = re.compile(r"^\s*\d+\.\d+\.\d+\.\d+\s*$")
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def check_valid_ipaddress(input_addr=None):
"""
Accept an input string with an IPv4 or IPv6 address. If the address is
@@ -2529,13 +2570,14 @@
assert (ipaddr_family == 4 or ipaddr_family == 6), error
return (input_addr, ipaddr_family)
[email protected](default=True, onerror=lambda _: sys.exit(1))
-def reverse_dns_lookup(input_str, timeout=3.0, server="", proto="udp"):
[email protected](reraise=True)
+def reverse_dns_lookup(input_str, timeout=3.0, server="4.2.2.2", proto="udp"):
"""Perform a simple reverse DNS lookup on an IPv4 or IPv6 address; return
results in a python dictionary"""
assert isinstance(proto, str) and (proto=="udp" or proto=="tcp")
assert isinstance(float(timeout), float) and float(timeout) > 0.0
- input_str, ipaddr_family = check_valid_ipaddress(input_str)
+ addr, addr_family = check_valid_ipaddress(input_str)
+ assert addr_family==4 or addr_family==6
tcp_flag = None
if proto=="tcp":
@@ -2546,12 +2588,16 @@
raise ValueError()
rr = Resolver()
+ rr.nameservers = []
+
+ # Append valid addresses to rr.nameservers...
+ for candidate_server_addr in server.split(","):
+ addr, addr_family =
check_valid_ipaddress(input_addr=candidate_server_addr)
+ rr.nameservers.append(addr)
+
#rr = rr.resolve_address(ipaddr=input_str, tcp=tcp_flag, rdtype="PTR",
lifetime=float(timeout))
#rr = rr.resolve_address(ipaddr=input_str, tcp=tcp_flag,
lifetime=float(timeout))
- if server != "":
- rr.nameservers = [server]
-
records = []
retval = {}
try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/ciscoconfparse-1.6.41/ciscoconfparse/ciscoconfparse.py
new/ciscoconfparse-1.6.50/ciscoconfparse/ciscoconfparse.py
--- old/ciscoconfparse-1.6.41/ciscoconfparse/ciscoconfparse.py 2022-09-10
00:25:02.491401000 +0200
+++ new/ciscoconfparse-1.6.50/ciscoconfparse/ciscoconfparse.py 2022-10-22
04:32:00.204709500 +0200
@@ -38,9 +38,6 @@
import re
import os
-from loguru import logger
-import toml
-
from ciscoconfparse.models_cisco import IOSHostnameLine, IOSRouteLine
from ciscoconfparse.models_cisco import IOSIntfLine
from ciscoconfparse.models_cisco import IOSAccessLine, IOSIntfGlobal
@@ -81,97 +78,110 @@
from ciscoconfparse.ccp_abc import BaseCfgLine
from ciscoconfparse.ccp_util import junos_unsupported
-from ciscoconfparse.ccp_util import ccp_logger_control
+from ciscoconfparse.ccp_util import configure_loguru
# Not using ccp_re yet... still a work in progress
# from ciscoconfparse.ccp_util import ccp_re
+from loguru import logger
+import toml
[email protected](default=True, onerror=lambda _: sys.exit(1))
-def configure_loguru(
- sink=sys.stderr,
- action="",
- # rotation="midnight",
- # retention="1 month",
- # compression="zip",
- level="DEBUG",
- colorize=True,
- debug=0,
-):
[email protected](reraise=True)
+def get_version_number():
"""
- configure_loguru()
+ Read the version number from 'pyproject.toml', or use version 0.0.0 in odd
+ circumstances.
"""
- assert isinstance(action, str)
- assert action in ('remove', 'add', 'enable', 'disable', '',)
- # assert isinstance(rotation, str)
- # assert isinstance(retention, str)
- # assert isinstance(compression, str)
- # assert compression == "zip"
- assert isinstance(level, str)
- assert isinstance(colorize, bool)
- assert isinstance(debug, int) and (0 <= debug <= 5)
-
- # logger_control() was imported above...
- # Remove the default loguru logger to stderr (handler_id==0)...
- ccp_logger_control(action="remove", handler_id=0)
-
-# _logger_config = logger.configure(
-# sys.stdout,
-# level="DEBUG",
-# rotation='midnight',
-# retention="1 month",
-# compression=compression,
-# colorize=colorize,
-# )
-# logger.add(_logger_config)
-
- ccp_logger_control(
- sink=sys.stdout,
- action="add",
- level="DEBUG",
- # rotation='midnight', # ALE barks about the rotation keyword...
- # retention="1 month",
- # compression=compression,
- colorize=colorize
+ # Docstring props: http://stackoverflow.com/a/1523456/667301
+ # version: if-else below fixes Github issue #123
+
+ version = "0.0.0" # version read failed
+
+ pyproject_toml_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "../pyproject.toml",
)
- ccp_logger_control(action="enable")
+ if os.path.isfile(pyproject_toml_path):
+ # Retrieve the version number from pyproject.toml...
+ toml_values = dict()
+ with open(pyproject_toml_path, encoding=ENCODING) as fh:
+ toml_values = toml.loads(fh.read())
+ version = toml_values["tool"]["poetry"].get("version", -1.0)
+ assert isinstance(version, str)
-configure_loguru()
+ else:
+ # This is required for importing from a zipfile... Github issue #123
+ version = "0.0.0" # __version__ read failed
-ENCODING = locale.getpreferredencoding()
-ALL_VALID_SYNTAX = (
- 'ios',
- 'nxos',
- 'asa',
- 'junos',
- 'terraform',
-)
-
-# Docstring props: http://stackoverflow.com/a/1523456/667301
-# __version__ if-else below fixes Github issue #123
-pyproject_path = os.path.join(
- os.path.dirname(os.path.abspath(__file__)),
- "../pyproject.toml",
-)
-if os.path.isfile(pyproject_path):
- # Retrieve the version number from pyproject.toml...
- toml_values = dict()
- with open(pyproject_path, encoding=ENCODING) as fh:
- toml_values = toml.loads(fh.read())
- __version__ = toml_values.get("version")
-
-else:
- # This case is required for importing from a zipfile... Github issue #123
- __version__ = "0.0.0" # __version__ read failed
-
-__author_email__ = r"mike /at\ pennington [dot] net"
-__author__ = "David Michael Pennington <{}>".format(__author_email__)
-__copyright__ = "2007-{}, {}".format(time.strftime("%Y"), __author__)
-__license__ = "GPLv3"
-__status__ = "Production"
+ return version
[email protected](reraise=True)
+def initialize_globals():
+ """
+ Initialize ciscoconfparse global dunder variables and a couple others.
+ """
+ global ALL_VALID_SYNTAX
+ global ENCODING
+ global __author_email__
+ global __author__
+ global __copyright__
+ global __license__
+ global __status__
+ global __version__
+
+ ENCODING = locale.getpreferredencoding()
+ ALL_VALID_SYNTAX = (
+ 'ios',
+ 'nxos',
+ 'asa',
+ 'junos',
+ 'terraform',
+ )
[email protected](default=True, onerror=lambda _: sys.exit(1))
+ try:
+ __author_email__ = r"mike /at\ pennington [dot] net"
+ __author__ = "David Michael Pennington <{}>".format(__author_email__)
+ __copyright__ = "2007-{}, {}".format(time.strftime("%Y"), __author__)
+ __license__ = "GPLv3"
+ __status__ = "Production"
+ __version__ = get_version_number()
+
+ except:
+ raise ValueError()
+
+ finally:
+ # These are all the 'dunder variables' required...
+ globals_dict = {
+ '__author_email__': __author_email__,
+ '__author__': __author__,
+ '__copyright__': __copyright__,
+ '__license__': __license__,
+ '__status__': __status__,
+ '__version__': __version__,
+ }
+ return globals_dict
+
[email protected](reraise=True)
+def initialize_ciscoconfparse():
+ """
+ Initialize ciscoconfparse global variables and configure logging
+ """
+ configure_loguru()
+
+ globals_dict = initialize_globals()
+ for key, value in globals_dict.items():
+ # Example, this will set __version__ to content of 'value'
+ # from -> https://stackoverflow.com/a/3972978/667301
+ globals()[key] = value
+
+ return globals_dict
+
+
+# ALL ciscoconfparse global variables initizalization happens here...
+initialize_ciscoconfparse()
+
+
[email protected](reraise=True)
def _parse_line_braces(line_txt=None, comment_delimiter=None) -> tuple:
"""
"""
@@ -281,7 +291,7 @@
raise ValueError('Cannot parse {}:"{}"'.format(syntax,
line_txt))
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def build_space_tolerant_regex(linespec):
r"""SEMI-PRIVATE: Accept a string, and return a string with all
spaces replaced with '\s+'"""
@@ -302,7 +312,7 @@
return linespec
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def assign_parent_to_closing_braces(input_list=None):
"""
Accept a list of brace-delimited BaseCfgLine() objects; these objects
@@ -335,16 +345,25 @@
for obj in input_list:
assert isinstance(obj, BaseCfgLine)
assert isinstance(obj.text, str)
- if len(obj.text)>=1 and obj.text.rstrip()[-1] == '{':
+
+ # These rstrip() are one of two fixes, intended to catch user
error such as
+ # the problems that the submitter of Github issue #251 had.
+ # CiscoConfParse() could not read his configuration because he
submitted
+ # a multi-line string...
+ #
+ # This check will explicitly catch some problems like that...
+ if len(obj.text.rstrip())>=1 and obj.text.rstrip()[-1] == '{':
opening_brace_objs.append(obj)
- elif len(obj.text)>=1 and obj.text.lstrip()[0]=='}':
+
+ elif len(obj.text.strip())>=1 and obj.text.strip()[0]=='}':
assert len(opening_brace_objs) >= 1
obj.parent = opening_brace_objs.pop()
+
return input_list
# This method was copied from the same method in git commit below...
#
https://raw.githubusercontent.com/mpenning/ciscoconfparse/bb3f77436023873da344377d3c839387f5131e7f/ciscoconfparse/ciscoconfparse.py
[email protected](default=True, onerror=lambda _: sys.exit(1))
[email protected](reraise=True)
def convert_junos_to_ios(input_list=None, stop_width=4, comment_delimiter="!",
debug=0):
"""
@@ -383,7 +402,7 @@
# IMPORTANT: do NOT decorate CiscoConfParse().__init__()
#
# Something breaks in CiscoConfParse() if using @logger.catch, below...
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def __init__(
self,
config="",
@@ -469,6 +488,7 @@
self.factory = factory
self.ConfigObjs = None
self.syntax = syntax
+ self.ignore_blank_lines = ignore_blank_lines
self.encoding = encoding or ENCODING
self.debug = debug
@@ -550,22 +570,22 @@
raise ValueError(error)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def __repr__(self):
if isinstance(self.ConfigObjs, (list, tuple, MutableSequence)):
num_lines = str(len(self.ConfigObjs))
elif self.ConfigObjs is None:
num_lines = "None"
return (
- "<CiscoConfParse: %s lines / syntax: %s / comment delimiter: '%s'
/ factory: %s / encoding: '%s'>"
+ "<CiscoConfParse: %s lines / syntax: %s / comment delimiter: '%s'
/ factory: %s / ignore_blank_lines: %s / encoding: '%s'>"
% (
num_lines, self.syntax, self.comment_delimiter,
- self.factory, self.encoding,
+ self.factory, self.ignore_blank_lines, self.encoding,
)
)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def get_config_lines(self, config=None, logger=None,
linesplit_rgx=r"\r*\n+"):
"""
Enforce rules - If config is a str, assume it's a filepath. If config
is a list, assume it's a router config.
@@ -601,8 +621,10 @@
else:
raise ValueError("config='%s' is an unexpected type()" % config)
+ #########################################################################
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ # do NOT wrap this method in logger.catch() - github issue #249
+ #########################################################################
@property
def openargs(self):
"""Fix for Py3.5 deprecation of universal newlines - Ref Github #114
@@ -636,7 +658,7 @@
return self.ConfigObjs
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def atomic(self):
"""Call :func:`~ciscoconfparse.CiscoConfParse.atomic` to manually fix
up ``ConfigObjs`` relationships
@@ -665,7 +687,7 @@
self.ConfigObjs._bootstrap_from_text()
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def commit(self):
"""
Alias for calling the :func:`~ciscoconfparse.CiscoConfParse.atomic`
@@ -798,7 +820,7 @@
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def convert_terraform_to_ios(self, input_list, stop_width=4, quotes=False,
comment_delimiter="#"):
"""
This method accepts `input_list` (it should be a list of
@@ -829,7 +851,7 @@
return lines
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_object_branches(
self,
branchspec=(),
@@ -1110,7 +1132,7 @@
return branches
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_interface_objects(self, intfspec, exactmatch=True):
"""Find all :class:`~cisco.IOSCfgLine` or
:class:`~models_cisco.NXOSCfgLine` objects whose text
@@ -1179,7 +1201,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_objects_dna(self, dnaspec, exactmatch=False):
"""Find all :class:`~models_cisco.IOSCfgLine` objects whose text
matches ``dnaspec`` and return the :class:`~models_cisco.IOSCfgLine`
@@ -1253,7 +1275,7 @@
)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_objects(self, linespec, exactmatch=False, ignore_ws=False):
"""Find all :class:`~models_cisco.IOSCfgLine` objects whose text
matches ``linespec`` and return the :class:`~models_cisco.IOSCfgLine`
@@ -1317,7 +1339,7 @@
return self._find_line_OBJ(linespec, exactmatch)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_lines(self, linespec, exactmatch=False, ignore_ws=False):
"""This method is the equivalent of a simple configuration grep
(Case-sensitive).
@@ -1349,7 +1371,7 @@
)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_children(self, linespec, exactmatch=False, ignore_ws=False):
"""Returns the parents matching the linespec, and their immediate
children. This method is different than :meth:`find_all_children`,
@@ -1404,7 +1426,7 @@
return [ii.text for ii in sorted(allobjs)]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_all_children(self, linespec, exactmatch=False, ignore_ws=False):
"""Returns the parents matching the linespec, and all their children.
This method is different than :meth:`find_children`, because
@@ -1482,7 +1504,7 @@
return [ii.text for ii in sorted(allobjs)]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_blocks(self, linespec, exactmatch=False, ignore_ws=False):
"""Find all siblings matching the linespec, then find all parents of
those siblings. Return a list of config lines sorted by line number,
@@ -1605,7 +1627,7 @@
return [ii.text for ii in sorted(tmp)]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_objects_w_child(
self,
parentspec,
@@ -1710,7 +1732,7 @@
)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_objects_w_all_children(
self,
parentspec,
@@ -1828,7 +1850,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_objects_w_missing_children(
self,
parentspec,
@@ -1877,7 +1899,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_parents_w_child(self, parentspec, childspec, ignore_ws=False):
"""Parse through all children matching childspec, and return a list of
parents that matched the parentspec. Only the parent lines will be
@@ -1965,7 +1987,7 @@
return [ii.text for ii in tmp]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_objects_wo_child(self, parentspec, childspec, ignore_ws=False):
r"""Return a list of parent :class:`~models_cisco.IOSCfgLine` objects,
which matched the ``parentspec`` and whose children did not match
``childspec``. Only the parent :class:`~models_cisco.IOSCfgLine` objects will
be returned. For simplicity, this method only finds oldest_ancestors without
immediate children that match.
@@ -2053,7 +2075,7 @@
]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_parents_wo_child(self, parentspec, childspec, ignore_ws=False):
r"""Parse through all parents matching parentspec, and return a list
of parents that did NOT have children match the childspec. For simplicity,
this method only finds oldest_ancestors without immediate children that match.
@@ -2140,7 +2162,7 @@
return [ii.text for ii in tmp]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_children_w_parents(self, parentspec, childspec, ignore_ws=False):
r"""Parse through the children of all parents matching parentspec,
and return a list of children that matched the childspec.
@@ -2251,7 +2273,7 @@
return [ii.text for ii in sorted(retval)]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_objects_w_parents(self, parentspec, childspec, ignore_ws=False):
r"""Parse through the children of all parents matching parentspec,
and return a list of child objects, which matched the childspec.
@@ -2352,7 +2374,7 @@
return sorted(retval)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_lineage(self, linespec, exactmatch=False):
"""
Iterate through to the oldest ancestor of this object, and return
@@ -2381,7 +2403,7 @@
return [obj.text for obj in tmp[0].lineage]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def has_line_with(self, linespec):
# https://stackoverflow.com/a/16097112/667301
matching_conftext = list(
@@ -2393,7 +2415,7 @@
return bool(matching_conftext)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def insert_before(
self,
exist_val="",
@@ -2495,7 +2517,7 @@
return [ii.text for ii in sorted(objs)]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def insert_after(
self,
exist_val="",
@@ -2602,7 +2624,7 @@
return [ii.text for ii in sorted(objs)]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def insert_after_child(
self,
parentspec,
@@ -2643,7 +2665,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def delete_lines(self, linespec, exactmatch=False, ignore_ws=False):
"""Find all :class:`~models_cisco.IOSCfgLine` objects whose text
matches linespec, and delete the object"""
@@ -2655,7 +2677,7 @@
obj.delete()
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def prepend_line(self, linespec):
"""Unconditionally insert an :class:`~models_cisco.IOSCfgLine` object
for ``linespec`` (a text line) at the top of the configuration"""
@@ -2663,7 +2685,7 @@
return self.ConfigObjs[0]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def append_line(self, linespec):
"""Unconditionally insert ``linespec`` (a text line) at the end of the
configuration
@@ -2682,7 +2704,7 @@
return self.ConfigObjs[-1]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def replace_lines(
self,
linespec,
@@ -2799,7 +2821,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def replace_children(
self,
parentspec,
@@ -2887,7 +2909,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def replace_all_children(
self,
parentspec,
@@ -2923,7 +2945,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def re_search_children(self, regex, recurse=False):
"""Use ``regex`` to search for root parents in the config with text
matching regex. If `recurse` is False, only root parent objects are returned.
A list of matching objects is returned.
@@ -2953,7 +2975,7 @@
return [obj for obj in self.find_objects(regex)]
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def re_match_iter_typed(
self,
regex,
@@ -3059,7 +3081,7 @@
return result_type(default)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def req_cfgspec_all_diff(self, cfgspec, ignore_ws=False):
"""
req_cfgspec_all_diff takes a list of required configuration lines,
@@ -3127,7 +3149,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def req_cfgspec_excl_diff(self, linespec, uncfgspec, cfgspec):
r"""
req_cfgspec_excl_diff accepts a linespec, an unconfig spec, and
@@ -3205,7 +3227,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def _sequence_nonparent_lines(self, a_nonparent_objs, b_nonparent_objs):
"""Assume a_nonparent_objs is the existing config sequence, and
b_nonparent_objs is the *desired* config sequence
@@ -3249,7 +3271,7 @@
return a_parse, a_lines, a_linenums
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def _sequence_parent_lines(self, a_parent_objs, b_parent_objs):
"""Assume a_parent_objs is the existing config sequence, and
b_parent_objs is the *desired* config sequence
@@ -3315,7 +3337,7 @@
return a_parse, a_lines, a_linenums
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def sync_diff(
self,
cfgspec,
@@ -3695,7 +3717,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def save_as(self, filepath):
"""Save a text copy of the configuration at ``filepath``; this
method uses the OperatingSystem's native line separators (such as
@@ -3713,7 +3735,7 @@
### or iterable of objects instead of the configuration text itself.
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def _find_line_OBJ(self, linespec, exactmatch=False):
"""SEMI-PRIVATE: Find objects whose text matches the linespec"""
@@ -3741,7 +3763,7 @@
)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def _find_sibling_OBJ(self, lineobject):
"""SEMI-PRIVATE: Takes a singe object and returns a list of sibling
objects"""
@@ -3749,7 +3771,7 @@
return siblings
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def _find_all_child_OBJ(self, lineobject):
"""SEMI-PRIVATE: Takes a single object and returns a list of
decendants in all 'children' / 'grandchildren' / etc... after it.
@@ -3764,7 +3786,7 @@
return retval
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def _unique_OBJ(self, objectlist):
"""SEMI-PRIVATE: Returns a list of unique objects (i.e. with no
duplicates).
@@ -3776,7 +3798,7 @@
return sorted(retval)
# This method is on CiscoConfParse()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def _objects_to_uncfg(self, objectlist, unconflist):
# Used by req_cfgspec_excl_diff()
retval = list()
@@ -3797,7 +3819,7 @@
"""
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def __init__(
self,
before_config=None,
@@ -3891,12 +3913,12 @@
self.sort_lines(parse_after, self.all_output_dicts)
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def raw_diff_dicts(self):
return self.all_output_dicts
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def unified_diff_header(self):
"""
Return a unified diff header similar to this...
@@ -3946,7 +3968,7 @@
return unified_diff_header
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def unified_diffs(self, header=True):
"""
Return a python list of text which contains the unified diff of the
@@ -3974,7 +3996,7 @@
return unified_diff_list
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def sort_lines(self, after_lines, all_output_dicts):
"""
Typical output line dict-format...
@@ -3989,7 +4011,7 @@
pass
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def dict_diffs(self, before_obj_list, after_obj_list):
############################################
# Render diffs
@@ -4040,7 +4062,7 @@
return all_dict_lines
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def build_diff_obj_list(
self, parse=None, default_diff_word=None, consider_whitespace=False
):
@@ -4068,7 +4090,7 @@
return retval
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def find_in_before_obj_list(
self, before_obj_list, after_obj, consider_whitespace=False, debug=0
):
@@ -4161,7 +4183,7 @@
return before_obj_list, after_obj
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def render_after_obj_diffs(self, aobj=None):
"""
Print after_obj (aobj) diffs to stdout. before_obj should not be
@@ -4215,7 +4237,7 @@
return output
# This method is on HDiff()
- @logger.catch(default=True, onerror=lambda _: sys.exit(1))
+ @logger.catch(reraise=True)
def compress_dict_diffs(self, all_lines=None):
"""
Summary
@@ -4403,6 +4425,15 @@
# FIXME the CiscoConfParse attribute / parameter should go away
# use self.ccp_ref instead of self.CiscoConfParse
#######################################################################
+
+ # This assert is one of two fixes, intended to catch user error such as
+ # the problems that the submitter of Github issue #251 had.
+ # CiscoConfParse() could not read his configuration because he
submitted
+ # a multi-line string...
+ #
+ # This check will explicitly catch some problems like that...
+ assert isinstance(initlist, (list, tuple, MutableSequence))
+
ciscoconfparse_kwarg_val = kwargs.get("CiscoConfParse", None)
ccp_ref_kwarg_val = kwargs.get("ccp_ref", None)
if ciscoconfparse_kwarg_val is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ciscoconfparse-1.6.41/pyproject.toml
new/ciscoconfparse-1.6.50/pyproject.toml
--- old/ciscoconfparse-1.6.41/pyproject.toml 2022-09-10 00:27:51.814184000
+0200
+++ new/ciscoconfparse-1.6.50/pyproject.toml 2022-10-22 04:32:00.204709500
+0200
@@ -1,6 +1,6 @@
[tool.poetry]
name = "ciscoconfparse"
-version = "1.6.41"
+version = "1.6.50"
description = "Parse, Audit, Query, Build, and Modify Cisco IOS-style and
JunOS-style configurations"
authors = [
"Mike Pennington <[email protected]>",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ciscoconfparse-1.6.41/setup.py
new/ciscoconfparse-1.6.50/setup.py
--- old/ciscoconfparse-1.6.41/setup.py 2022-09-10 00:29:24.075051000 +0200
+++ new/ciscoconfparse-1.6.50/setup.py 1970-01-01 01:00:00.000000000 +0100
@@ -15,13 +15,13 @@
setup_kwargs = {
'name': 'ciscoconfparse',
- 'version': '1.6.41',
+ 'version': '1.6.50',
'description': 'Parse, Audit, Query, Build, and Modify Cisco IOS-style and
JunOS-style configurations',
- 'long_description': 'ciscoconfparse\n==============\n\n[![Github unittest
workflow][4]][5] [![Code Health][37]][38] [![Version][2]][3]
[![Downloads][6]][7] [![License][8]][9]\n\n\nIntroduction: What is
ciscoconfparse?\n-------------------------------------\n\nShort answer:
ciscoconfparse is a [Python][10] library\nthat helps you quickly answer
questions like these about your\nconfigurations:\n\n- What interfaces are
shutdown?\n- Which interfaces are in trunk mode?\n- What address and subnet
mask is assigned to each interface?\n- Which interfaces are missing a critical
command?\n- Is this configuration missing a standard config line?\n\nIt can
help you:\n\n- Audit existing router / switch / firewall / wlc
configurations\n- Modify existing configurations\n- Build new
configurations\n\nSpeaking generally, the library examines an IOS-style config
and breaks\nit into a set of linked parent / child relationships. You can
perform\ncomplex queries about these relationships.\n\n[![Cisco
IOS config: Parent / child][11]][11]\n\nUsage\n-----\n\nThe following code
will parse a configuration stored in\n\\\'exampleswitch.conf\\\' and select
interfaces that are shutdown.\n\n```python\nfrom ciscoconfparse import
CiscoConfParse\n\nparse = CiscoConfParse(\'exampleswitch.conf\',
syntax=\'ios\')\n\nfor intf_obj in parse.find_objects_w_child(\'^interface\',
\'^\\s+shutdown\'):\n print("Shutdown: " + intf_obj.text)\n```\n\nThe next
example will find the IP address assigned to interfaces.\n\n```python\nfrom
ciscoconfparse import CiscoConfParse\n\nparse =
CiscoConfParse(\'exampleswitch.conf\', syntax=\'ios\')\n\nfor intf_obj in
parse.find_objects(\'^interface\'):\n\n intf_name =
intf_obj.re_match_typed(\'^interface\\s+(\\S.+?)$\')\n\n # Search children
of all interfaces for a regex match and return\n # the value matched in
regex match group 1. If there is no match,\n # return a default value:
\'\'\n intf_ip_addr = intf_obj.re_match_iter_typed(\n r\'ip\\sa
ddress\\s(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s\', result_type=str,\n group=1,
default=\'\')\n print("{0}: {1}".format(intf_name,
intf_ip_addr))\n```\n\nWhat if we don\\\'t use
Cisco?\n----------------------------\n\nDon\\\'t let that stop you.\n\nAs of
CiscoConfParse 1.2.4, you can parse [brace-delimited configurations][13] into a
Cisco IOS style (see [Github Issue \\#17][14]), which means that CiscoConfParse
can parse these configurations:\n\n- Juniper Networks Junos\n- Palo Alto
Networks Firewall configurations\n- F5 Networks
configurations\n\nCiscoConfParse also handles anything that has a Cisco IOS
style of configuration, which includes:\n\n- Cisco IOS, Cisco Nexus, Cisco
IOS-XR, Cisco IOS-XE, Aironet OS, Cisco ASA, Cisco CatOS\n- Arista EOS\n-
Brocade\n- HP Switches\n- Force 10 Switches\n- Dell PowerConnect Switches\n-
Extreme Networks\n- Enterasys\n- Screenos\n\nDocs\n----\n\n- The latest copy of
the docs are [archived on the web][15]\n- There is also a [CiscoConfParse Tuto
rial][16]\n\nEditing the Package\n-------------------\n\n- `git clone
https://github.com/mpenning/ciscoconfparse`\n- `cd ciscoconfparse`\n- `git
checkout -b develop`\n- Add / modify / delete on the `develop` branch\n-
`make test`\n- If tests run clean, `git commit` all the pending changes on
the `develop` branch\n- (as required) Edit the version number in
[pyproject.toml][12]\n- `git checkout main`\n- `git merge develop`\n-
`make test`\n- `make repo-push`\n- `make
pypi`\n\nPre-requisites\n--------------\n\n[The ciscoconfparse python
package][3] requires Python versions 3.6+ (note: Python version 3.7.0 has a bug
- ref [Github issue \\#117][18], but version 3.7.1 works); the OS should not
matter.\n\nInstallation and Downloads\n--------------------------\n\n- Use
`poetry` for Python3.x\\... :\n\n python -m pip install
ciscoconfparse\n\nIf you\\\'re interested in the source, you can always pull
from the [github repo][17]:\n\n- Download from [the github r
epo][17]: :\n\n git clone git://github.com/mpenning/ciscoconfparse\n
cd ciscoconfparse/\n python -m pip install .\n\nOther
Resources\n---------------\n\n- [Dive into
Python3](http://www.diveintopython3.net/) is a good way to learn Python\n-
[Team CYMRU][30] has a [Secure IOS Template][29], which is especially useful
for external-facing routers / switches\n- [Cisco\\\'s Guide to hardening IOS
devices][31]\n- [Center for Internet Security Benchmarks][32] (An email
address, cookies, and javascript are required)\n\nBug Tracker and
Support\n-----------------------\n\n- Please report any suggestions, bug
reports, or annoyances with a [github bug report][24].\n- If you\\\'re having
problems with general python issues, consider searching for a solution on
[Stack Overflow][33]. If you can\\\'t find a solution for your problem or need
more help, you can [ask on Stack Overflow][34] or [reddit/r/Python][39].\n- If
you\\\'re having problems with your Cisco devices, you can
contact:\n - [Cisco TAC][28]\n - [reddit/r/Cisco][35]\n -
[reddit/r/networking][36]\n -
[NetworkEngineering.se][23]\n\nUnit-Tests\n----------\n\nThe project\\\'s [test
workflow][1] checks ciscoconfparse on Python versions 3.6 and higher, as well
as a [pypy JIT][22] executable.\n\nClick the image below for details; the
current build status is: [![Github unittest status][4]][5]\n\nLicense and
Copyright\n---------------------\n\n[ciscoconfparse][3] is licensed
[GPLv3][21]\n\n- Copyright (C) 2021-2022 David Michael Pennington\n- Copyright
(C) 2020-2021 David Michael Pennington at Cisco Systems (post-acquisition:
Cisco acquired ThousandEyes)\n- Copyright (C) 2019 David Michael Pennington at
ThousandEyes\n- Copyright (C) 2012-2019 David Michael Pennington at Samsung
Data Services\n- Copyright (C) 2011-2012 David Michael Pennington at Dell
Computer Corp\n- Copyright (C) 2007-2011 David Michael Pennington\n\nThe word
\\"Cisco\\" is a registered trademark of [Cisco Systems][27].\n\nAutho
r\n------\n\n[ciscoconfparse][3] was written by [David Michael Pennington][25]
(mike \\[\\~at\\~\\] pennington \\[.dot.\\] net).\n\n\n [1]:
https://github.com/mpenning/ciscoconfparse/tree/master/.github/workflows\n
[2]: https://img.shields.io/pypi/v/ciscoconfparse.svg\n [3]:
https://pypi.python.org/pypi/ciscoconfparse/\n [4]:
https://github.com/mpenning/ciscoconfparse/actions/workflows/tests.yml/badge.svg\n
[5]: https://github.com/mpenning/ciscoconfparse/actions/workflows/tests.yml\n
[6]: https://pepy.tech/badge/ciscoconfparse\n [7]:
https://pepy.tech/project/ciscoconfparse\n [8]:
http://img.shields.io/badge/license-GPLv3-blue.svg\n [9]:
https://www.gnu.org/copyleft/gpl.html\n [10]: https://www.python.org\n [11]:
https://raw.githubusercontent.com/mpenning/ciscoconfparse/master/sphinx-doc/_static/ciscoconfparse_overview_75pct.png\n
[12]: https://github.com/mpenning/ciscoconfparse/blob/main/pyproject.toml\n
[13]: https://github.com/mpenning/ciscoconfparse/blob/master/conf
igs/sample_01.junos\n [14]:
https://github.com/mpenning/ciscoconfparse/issues/17\n [15]:
http://www.pennington.net/py/ciscoconfparse/\n [16]:
http://pennington.net/tutorial/ciscoconfparse/ccp_tutorial.html\n [17]:
https://github.com/mpenning/ciscoconfparse\n [18]:
https://github.com/mpenning/ciscoconfparse/issues/117\n [19]:
https://github.com/mpenning/ciscoconfparse/issues/13\n [20]:
https://github.com/CrackerJackMack/\n [21]:
http://www.gnu.org/licenses/gpl-3.0.html\n [22]: https://pypy.org\n [23]:
https://networkengineering.stackexchange.com/\n [24]:
https://github.com/mpenning/ciscoconfparse/issues/new/choose\n [25]:
https://github.com/mpenning\n [26]: https://github.com/muir\n [27]:
https://www.cisco.com/\n [28]: https://www.cisco.com/go/support\n [29]:
https://www.cymru.com/Documents/secure-ios-template.html\n [30]:
https://team-cymru.com/company/\n [31]:
http://www.cisco.com/c/en/us/support/docs/ip/access-lists/13608-21.html\n
[32]: https://learn.cisecurity
.org/benchmarks\n [33]: https://stackoverflow.com\n [34]:
http://stackoverflow.com/questions/ask\n [35]:
https://www.reddit.com/r/Cisco/\n [36]: https://www.reddit.com/r/networking\n
[37]: https://snyk.io/advisor/python/ciscoconfparse/badge.svg\n [38]:
https://snyk.io/advisor/python/ciscoconfparse\n [39]:
https://www.reddit.com/r/Python/\n',
+ 'long_description': 'ciscoconfparse\n==============\n\n[![Github unittest
workflow][4]][5] [![Code Health][37]][38] [![Version][2]][3]
[![Downloads][6]][7] [![License][8]][9]\n\n\nIntroduction: What is
ciscoconfparse?\n-------------------------------------\n\nShort answer:
ciscoconfparse is a [Python][10] library\nthat helps you quickly answer
questions like these about your\nconfigurations:\n\n- What interfaces are
shutdown?\n- Which interfaces are in trunk mode?\n- What address and subnet
mask is assigned to each interface?\n- Which interfaces are missing a critical
command?\n- Is this configuration missing a standard config line?\n\nIt can
help you:\n\n- Audit existing router / switch / firewall / wlc
configurations\n- Modify existing configurations\n- Build new
configurations\n\nSpeaking generally, the library examines an IOS-style config
and breaks\nit into a set of linked parent / child relationships. You can
perform\ncomplex queries about these relationships.\n\n[![Cisco
IOS config: Parent / child][11]][11]\n\nUsage\n-----\n\nThe following code
will parse a configuration stored in\n\\\'exampleswitch.conf\\\' and select
interfaces that are shutdown.\n\n```python\nfrom ciscoconfparse import
CiscoConfParse\n\nparse = CiscoConfParse(\'exampleswitch.conf\',
syntax=\'ios\')\n\nfor intf_obj in parse.find_objects_w_child(\'^interface\',
\'^\\s+shutdown\'):\n print("Shutdown: " + intf_obj.text)\n```\n\nThe next
example will find the IP address assigned to interfaces.\n\n```python\nfrom
ciscoconfparse import CiscoConfParse\n\nparse =
CiscoConfParse(\'exampleswitch.conf\', syntax=\'ios\')\n\nfor intf_obj in
parse.find_objects(\'^interface\'):\n\n intf_name =
intf_obj.re_match_typed(\'^interface\\s+(\\S.+?)$\')\n\n # Search children
of all interfaces for a regex match and return\n # the value matched in
regex match group 1. If there is no match,\n # return a default value:
\'\'\n intf_ip_addr = intf_obj.re_match_iter_typed(\n r\'ip\\sa
ddress\\s(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s\', result_type=str,\n group=1,
default=\'\')\n print("{0}: {1}".format(intf_name,
intf_ip_addr))\n```\n\nWhat if we don\\\'t use
Cisco?\n----------------------------\n\nDon\\\'t let that stop you.\n\nAs of
CiscoConfParse 1.2.4, you can parse [brace-delimited configurations][13] into a
Cisco IOS style (see [Github Issue \\#17][14]), which means that CiscoConfParse
can parse these configurations:\n\n- Juniper Networks Junos\n- Palo Alto
Networks Firewall configurations\n- F5 Networks
configurations\n\nCiscoConfParse also handles anything that has a Cisco IOS
style of configuration, which includes:\n\n- Cisco IOS, Cisco Nexus, Cisco
IOS-XR, Cisco IOS-XE, Aironet OS, Cisco ASA, Cisco CatOS\n- Arista EOS\n-
Brocade\n- HP Switches\n- Force 10 Switches\n- Dell PowerConnect Switches\n-
Extreme Networks\n- Enterasys\n- Screenos\n\nDocs\n----\n\n- The latest copy of
the docs are [archived on the web][15]\n- There is also a [CiscoConfParse Tuto
rial][16]\n\nEditing the Package\n-------------------\n\n- `git clone
https://github.com/mpenning/ciscoconfparse`\n- `cd ciscoconfparse`\n- `git
checkout -b develop`\n- Add / modify / delete on the `develop` branch\n-
`make test`\n- If tests run clean, `git commit` all the pending changes on
the `develop` branch\n- (as required) Edit the version number in
[pyproject.toml][12]\n- `git checkout main`\n- `git merge develop`\n-
`make test`\n- `make repo-push`\n- `make
pypi`\n\nPre-requisites\n--------------\n\n[The ciscoconfparse python
package][3] requires Python versions 3.7+ (note: Python version 3.7.0 has a bug
- ref [Github issue \\#117][18], but version 3.7.1 works); the OS should not
matter.\n\nInstallation and Downloads\n--------------------------\n\n- Use
`poetry` for Python3.x\\... :\n\n python -m pip install
ciscoconfparse\n\nIf you\\\'re interested in the source, you can always pull
from the [github repo][17]:\n\n- Download from [the github r
epo][17]: :\n\n git clone git://github.com/mpenning/ciscoconfparse\n
cd ciscoconfparse/\n python -m pip install .\n\nOther
Resources\n---------------\n\n- [Dive into
Python3](http://www.diveintopython3.net/) is a good way to learn Python\n-
[Team CYMRU][30] has a [Secure IOS Template][29], which is especially useful
for external-facing routers / switches\n- [Cisco\\\'s Guide to hardening IOS
devices][31]\n- [Center for Internet Security Benchmarks][32] (An email
address, cookies, and javascript are required)\n\nBug Tracker and
Support\n-----------------------\n\n- Please report any suggestions, bug
reports, or annoyances with a [github bug report][24].\n- If you\\\'re having
problems with general python issues, consider searching for a solution on
[Stack Overflow][33]. If you can\\\'t find a solution for your problem or need
more help, you can [ask on Stack Overflow][34] or [reddit/r/Python][39].\n- If
you\\\'re having problems with your Cisco devices, you can
contact:\n - [Cisco TAC][28]\n - [reddit/r/Cisco][35]\n -
[reddit/r/networking][36]\n -
[NetworkEngineering.se][23]\n\nUnit-Tests\n----------\n\nThe project\\\'s [test
workflow][1] checks ciscoconfparse on Python versions 3.6 and higher, as well
as a [pypy JIT][22] executable.\n\nClick the image below for details; the
current build status is: [![Github unittest status][4]][5]\n\nLicense and
Copyright\n---------------------\n\n[ciscoconfparse][3] is licensed
[GPLv3][21]\n\n- Copyright (C) 2021-2022 David Michael Pennington\n- Copyright
(C) 2020-2021 David Michael Pennington at Cisco Systems (post-acquisition:
Cisco acquired ThousandEyes)\n- Copyright (C) 2019 David Michael Pennington at
ThousandEyes\n- Copyright (C) 2012-2019 David Michael Pennington at Samsung
Data Services\n- Copyright (C) 2011-2012 David Michael Pennington at Dell
Computer Corp\n- Copyright (C) 2007-2011 David Michael Pennington\n\nThe word
\\"Cisco\\" is a registered trademark of [Cisco Systems][27].\n\nAutho
r\n------\n\n[ciscoconfparse][3] was written by [David Michael Pennington][25]
(mike \\[\\~at\\~\\] pennington \\[.dot.\\] net).\n\n\n [1]:
https://github.com/mpenning/ciscoconfparse/tree/master/.github/workflows\n
[2]: https://img.shields.io/pypi/v/ciscoconfparse.svg\n [3]:
https://pypi.python.org/pypi/ciscoconfparse/\n [4]:
https://github.com/mpenning/ciscoconfparse/actions/workflows/tests.yml/badge.svg\n
[5]: https://github.com/mpenning/ciscoconfparse/actions/workflows/tests.yml\n
[6]: https://pepy.tech/badge/ciscoconfparse\n [7]:
https://pepy.tech/project/ciscoconfparse\n [8]:
http://img.shields.io/badge/license-GPLv3-blue.svg\n [9]:
https://www.gnu.org/copyleft/gpl.html\n [10]: https://www.python.org\n [11]:
https://raw.githubusercontent.com/mpenning/ciscoconfparse/master/sphinx-doc/_static/ciscoconfparse_overview_75pct.png\n
[12]: https://github.com/mpenning/ciscoconfparse/blob/main/pyproject.toml\n
[13]: https://github.com/mpenning/ciscoconfparse/blob/master/conf
igs/sample_01.junos\n [14]:
https://github.com/mpenning/ciscoconfparse/issues/17\n [15]:
http://www.pennington.net/py/ciscoconfparse/\n [16]:
http://pennington.net/tutorial/ciscoconfparse/ccp_tutorial.html\n [17]:
https://github.com/mpenning/ciscoconfparse\n [18]:
https://github.com/mpenning/ciscoconfparse/issues/117\n [19]:
https://github.com/mpenning/ciscoconfparse/issues/13\n [20]:
https://github.com/CrackerJackMack/\n [21]:
http://www.gnu.org/licenses/gpl-3.0.html\n [22]: https://pypy.org\n [23]:
https://networkengineering.stackexchange.com/\n [24]:
https://github.com/mpenning/ciscoconfparse/issues/new/choose\n [25]:
https://github.com/mpenning\n [26]: https://github.com/muir\n [27]:
https://www.cisco.com/\n [28]: https://www.cisco.com/go/support\n [29]:
https://www.cymru.com/Documents/secure-ios-template.html\n [30]:
https://team-cymru.com/company/\n [31]:
http://www.cisco.com/c/en/us/support/docs/ip/access-lists/13608-21.html\n
[32]: https://learn.cisecurity
.org/benchmarks\n [33]: https://stackoverflow.com\n [34]:
http://stackoverflow.com/questions/ask\n [35]:
https://www.reddit.com/r/Cisco/\n [36]: https://www.reddit.com/r/networking\n
[37]: https://snyk.io/advisor/python/ciscoconfparse/badge.svg\n [38]:
https://snyk.io/advisor/python/ciscoconfparse\n [39]:
https://www.reddit.com/r/Python/\n',
'author': 'Mike Pennington',
'author_email': '[email protected]',
- 'maintainer': None,
- 'maintainer_email': None,
+ 'maintainer': 'None',
+ 'maintainer_email': 'None',
'url': 'https://github.com/mpenning/ciscoconfparse',
'packages': packages,
'package_data': package_data,