annet 3.8.0__tar.gz → 3.9.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of annet might be problematic. Click here for more details.
- {annet-3.8.0/annet.egg-info → annet-3.9.1}/PKG-INFO +1 -1
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/jsontools.py +76 -36
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/netdev/devdb/data/devdb.json +10 -1
- {annet-3.8.0 → annet-3.9.1}/annet/gen.py +8 -34
- {annet-3.8.0 → annet-3.9.1}/annet/generators/result.py +7 -4
- {annet-3.8.0 → annet-3.9.1}/annet/implicit.py +17 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/huawei.rul +6 -0
- {annet-3.8.0 → annet-3.9.1/annet.egg-info}/PKG-INFO +1 -1
- {annet-3.8.0 → annet-3.9.1}/AUTHORS +0 -0
- {annet-3.8.0 → annet-3.9.1}/LICENSE +0 -0
- {annet-3.8.0 → annet-3.9.1}/MANIFEST.in +0 -0
- {annet-3.8.0 → annet-3.9.1}/README.md +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/fetchers/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/fetchers/stub/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/fetchers/stub/fetcher.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/file/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/file/provider.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/adapter.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/client.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/manufacturer.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/query.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/status_client.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/storage_base.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/common/storage_opts.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/provider.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v24/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v24/models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v24/storage.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v37/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v37/models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v37/storage.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v41/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v41/models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v41/storage.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v42/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v42/models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/adapters/netbox/v42/storage.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annet.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/command.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/diff.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/errors.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/filter_acl.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/lib.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/netdev/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/netdev/db.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/netdev/devdb/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/netdev/views/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/netdev/views/dump.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/netdev/views/hardware.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/output.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/patching.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rbparser/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rbparser/acl.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rbparser/deploying.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rbparser/ordering.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rbparser/platform.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rbparser/syntax.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rulebook/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/rulebook/common.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/annlib/types.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/api/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/argparse.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/bgp_models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/cli.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/cli_args.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/configs/context.yml +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/configs/logging.yaml +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/connectors.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/deploy.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/deploy_ui.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/diff.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/executor.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/filtering.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/base.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/common/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/common/initial.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/entire.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/exceptions.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/jsonfragment.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/partial.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/perf.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/generators/ref.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/hardware.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/lib.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/basemodel.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/device_models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/executor.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/match_args.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/models_converter.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/peer_models.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/port_processor.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/mesh/registry.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/output.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/parallel.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/patching.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/reference.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/action.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/condition.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/match_builder.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/policy.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/result.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/routemap.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl/statement_builder.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/aspath.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/community.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/cumulus_frr.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/entities.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/execute.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/policy.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/prefix_lists.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rpl_generators/rd.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/arista/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/arista/aaa.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/arista/iface.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/aruba/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/aruba/ap_env.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/aruba/misc.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/b4com/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/b4com/file.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/b4com/iface.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/cisco/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/cisco/iface.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/cisco/misc.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/cisco/vlandb.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/common.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/deploying.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/generic/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/generic/misc.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/huawei/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/huawei/aaa.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/huawei/bgp.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/huawei/iface.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/huawei/misc.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/huawei/vlandb.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/juniper/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/juniper/iface.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/nexus/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/nexus/iface.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/patching.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/routeros/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/routeros/file.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/arista.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/arista.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/arista.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/aruba.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/aruba.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/aruba.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/b4com.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/b4com.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/b4com.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/cisco.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/cisco.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/cisco.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/huawei.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/huawei.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/iosxr.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/iosxr.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/iosxr.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/juniper.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/juniper.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/nexus.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/nexus.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/nexus.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/nokia.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/optixtrans.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/optixtrans.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/optixtrans.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/pc.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/pc.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/pc.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/ribbon.deploy +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/ribbon.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/routeros.order +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/rulebook/texts/routeros.rul +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/storage.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/text_term_format.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/tracing.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/types.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/base.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/arista.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/aruba.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/b4com.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/cisco.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/h3c.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/huawei.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/iosxr.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/juniper.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/nexus.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/nokia.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/optixtrans.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/pc.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/ribbon.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/library/routeros.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/registry.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet/vendors/tabparser.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet.egg-info/SOURCES.txt +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet.egg-info/dependency_links.txt +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet.egg-info/entry_points.txt +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet.egg-info/requires.txt +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet.egg-info/top_level.txt +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/example/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/example/hostname.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/example/lldp.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/mesh_example/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/mesh_example/bgp.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/mesh_example/mesh_logic.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/rpl_example/__init__.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/rpl_example/generator.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/rpl_example/items.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/rpl_example/mesh.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/annet_generators/rpl_example/route_policy.py +0 -0
- {annet-3.8.0 → annet-3.9.1}/requirements.txt +0 -0
- {annet-3.8.0 → annet-3.9.1}/setup.cfg +0 -0
- {annet-3.8.0 → annet-3.9.1}/setup.py +0 -0
|
@@ -4,8 +4,9 @@ import copy
|
|
|
4
4
|
import fnmatch
|
|
5
5
|
import json
|
|
6
6
|
from collections.abc import Mapping, Sequence
|
|
7
|
+
from itertools import starmap
|
|
7
8
|
from operator import itemgetter
|
|
8
|
-
from typing import Any, Dict, List, Optional
|
|
9
|
+
from typing import Any, Dict, Iterable, List, Optional
|
|
9
10
|
|
|
10
11
|
import jsonpatch
|
|
11
12
|
import jsonpointer
|
|
@@ -16,23 +17,28 @@ def format_json(data: Any, stable: bool = False) -> str:
|
|
|
16
17
|
return json.dumps(data, indent=4, ensure_ascii=False, sort_keys=not stable) + "\n"
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
def _sanitize_json_pointer(pattern: str) -> str:
|
|
20
|
-
"""Replace special characters on the JsonPointer valid ones"""
|
|
21
|
-
return pattern.replace("~", "~0").replace("/", "~1")
|
|
22
|
-
|
|
23
|
-
|
|
24
20
|
def apply_json_fragment(
|
|
25
21
|
old: Dict[str, Any],
|
|
26
|
-
new_fragment: Dict[str, Any],
|
|
27
|
-
acl:
|
|
22
|
+
new_fragment: Dict[str, Any], *,
|
|
23
|
+
acl: Sequence[str],
|
|
24
|
+
filters: Sequence[str] | None = None,
|
|
28
25
|
) -> Dict[str, Any]:
|
|
29
26
|
"""
|
|
30
27
|
Replace parts of the old document with 'new_fragment' using ACL restrictions.
|
|
28
|
+
If `filter` is not `None`, only those parts which also matches at least one filter
|
|
29
|
+
from the list will be modified (updated or deleted).
|
|
31
30
|
"""
|
|
32
31
|
full_new_config = copy.deepcopy(old)
|
|
33
32
|
for acl_item in acl:
|
|
34
33
|
new_pointers = _resolve_json_pointers(acl_item, new_fragment)
|
|
35
34
|
old_pointers = _resolve_json_pointers(acl_item, full_new_config)
|
|
35
|
+
if filters is not None:
|
|
36
|
+
new_pointers = _apply_filters_to_json_pointers(
|
|
37
|
+
new_pointers, filters, content=new_fragment
|
|
38
|
+
)
|
|
39
|
+
old_pointers = _apply_filters_to_json_pointers(
|
|
40
|
+
old_pointers, filters, content=full_new_config
|
|
41
|
+
)
|
|
36
42
|
|
|
37
43
|
for pointer in new_pointers:
|
|
38
44
|
new_value = pointer.get(new_fragment)
|
|
@@ -102,30 +108,7 @@ def apply_patch(content: Optional[bytes], patch_bytes: bytes) -> bytes:
|
|
|
102
108
|
return new_contents
|
|
103
109
|
|
|
104
110
|
|
|
105
|
-
def
|
|
106
|
-
result = {}
|
|
107
|
-
for f in filters:
|
|
108
|
-
filter_text = f.strip()
|
|
109
|
-
if not filter_text:
|
|
110
|
-
continue
|
|
111
|
-
|
|
112
|
-
pointers = _resolve_json_pointers(filter_text, content)
|
|
113
|
-
for pointer in pointers:
|
|
114
|
-
part = pointer.get(copy.deepcopy(content))
|
|
115
|
-
|
|
116
|
-
sub_tree = result
|
|
117
|
-
for i in pointer.get_parts():
|
|
118
|
-
if i not in sub_tree:
|
|
119
|
-
sub_tree[i] = {}
|
|
120
|
-
sub_tree = sub_tree[i]
|
|
121
|
-
|
|
122
|
-
patch = jsonpatch.JsonPatch([{"op": "add", "path": pointer.path, "value": part}])
|
|
123
|
-
result = patch.apply(result)
|
|
124
|
-
|
|
125
|
-
return result
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
def _resolve_json_pointers(pattern: str, content: Dict[str, Any]) -> List[jsonpointer.JsonPointer]:
|
|
111
|
+
def _resolve_json_pointers(pattern: str, content: dict[str, Any]) -> list[jsonpointer.JsonPointer]:
|
|
129
112
|
"""
|
|
130
113
|
Resolve globbed json pointer pattern to a list of actual pointers, existing in the document.
|
|
131
114
|
|
|
@@ -163,7 +146,7 @@ def _resolve_json_pointers(pattern: str, content: Dict[str, Any]) -> List[jsonpo
|
|
|
163
146
|
]
|
|
164
147
|
"""
|
|
165
148
|
parts = jsonpointer.JsonPointer(pattern).parts
|
|
166
|
-
matched = [(
|
|
149
|
+
matched = [((), content)]
|
|
167
150
|
for part in parts:
|
|
168
151
|
new_matched = []
|
|
169
152
|
for matched_parts, doc in matched:
|
|
@@ -179,10 +162,67 @@ def _resolve_json_pointers(pattern: str, content: Dict[str, Any]) -> List[jsonpo
|
|
|
179
162
|
if fnmatch.fnmatchcase(str(i), part)
|
|
180
163
|
]
|
|
181
164
|
for key, sub_doc in keys_and_docs:
|
|
182
|
-
new_matched.append((matched_parts +
|
|
165
|
+
new_matched.append((matched_parts + (key,), sub_doc))
|
|
183
166
|
matched = new_matched
|
|
184
167
|
|
|
185
|
-
ret:
|
|
168
|
+
ret: list[jsonpointer.JsonPointer] = []
|
|
186
169
|
for matched_parts, _ in matched:
|
|
187
|
-
ret.append(jsonpointer.JsonPointer
|
|
170
|
+
ret.append(jsonpointer.JsonPointer.from_parts(matched_parts))
|
|
188
171
|
return ret
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _apply_filters_to_json_pointers(
|
|
175
|
+
pointers: Iterable[jsonpointer.JsonPointer],
|
|
176
|
+
filters: Sequence[str], *,
|
|
177
|
+
content: Any,
|
|
178
|
+
) -> list[jsonpointer.JsonPointer]:
|
|
179
|
+
|
|
180
|
+
"""
|
|
181
|
+
Takes a list of pointers, a list of filters and a document
|
|
182
|
+
and returns a list of pointers that match at least one of the filters
|
|
183
|
+
(if necessary, pointers may be deeper than from the input).
|
|
184
|
+
|
|
185
|
+
For example, given:
|
|
186
|
+
pointers=["/foo", "/lorem/ipsum", "/lorem/dolor"],
|
|
187
|
+
filters=["/foo/b*/q*", "/lorem"],
|
|
188
|
+
content={
|
|
189
|
+
"foo": {
|
|
190
|
+
"bar": {
|
|
191
|
+
"baz": [1, 2],
|
|
192
|
+
"qux": [3, 4]
|
|
193
|
+
},
|
|
194
|
+
"qux": {
|
|
195
|
+
"baz": [5, 6]
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
"lorem": {
|
|
199
|
+
"ipsum": [7, 8],
|
|
200
|
+
"dolor": "sit",
|
|
201
|
+
"amet": "consectetur"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
The function will return:
|
|
205
|
+
["/foo/bar/qux", "/lorem/ipsum", "/lorem/dolor"]
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
ret: set[jsonpointer.JsonPointer] = set()
|
|
209
|
+
for filter_item in filters:
|
|
210
|
+
filter_parts = jsonpointer.JsonPointer(filter_item).parts
|
|
211
|
+
for pointer in pointers:
|
|
212
|
+
pointer_parts = pointer.parts
|
|
213
|
+
if not all(starmap(fnmatch.fnmatchcase, zip(pointer_parts, filter_parts))):
|
|
214
|
+
continue # common part not matched
|
|
215
|
+
if len(filter_parts) > len(pointer_parts):
|
|
216
|
+
# filter is deeper than data pointer
|
|
217
|
+
deeper_doc = pointer.resolve(content)
|
|
218
|
+
deeper_pattern = "".join((
|
|
219
|
+
f"/{jsonpointer.escape(part)}"
|
|
220
|
+
for part in filter_parts[len(pointer_parts):]
|
|
221
|
+
))
|
|
222
|
+
ret.update(map(pointer.join, _resolve_json_pointers(deeper_pattern, deeper_doc)))
|
|
223
|
+
else:
|
|
224
|
+
ret.add(pointer)
|
|
225
|
+
# sort return value by some stable key, to decrease the chance
|
|
226
|
+
# that some bug may lead to unstable output being produced
|
|
227
|
+
# (since `type(ret) is set`)
|
|
228
|
+
return sorted(ret, key=str)
|
|
@@ -63,7 +63,12 @@
|
|
|
63
63
|
"Huawei.Quidway.S2x.S2300": "23\\d\\d",
|
|
64
64
|
"Huawei.Quidway.S2x.S2700": "27\\d\\d",
|
|
65
65
|
"Huawei.Quidway.S5300": "53\\d\\d",
|
|
66
|
+
"Huawei.Quidway.S5300.S5328": "5328",
|
|
67
|
+
"Huawei.Quidway.S5300.S5352": "5352",
|
|
66
68
|
"Huawei.Quidway.S5700": "57\\d\\d",
|
|
69
|
+
"Huawei.Quidway.S5700.S5731": "5731",
|
|
70
|
+
"Huawei.Quidway.S5700.S5735": "5735",
|
|
71
|
+
"Huawei.Quidway.S5700.S5735I": "5735I",
|
|
67
72
|
"Huawei.Quidway.S6700": "67\\d\\d",
|
|
68
73
|
"Huawei.NE": " NE\\d+",
|
|
69
74
|
"Huawei.NE.NE40E": " NE40E",
|
|
@@ -152,8 +157,12 @@
|
|
|
152
157
|
"Aruba.AP.AP300.AP367": " AP-367",
|
|
153
158
|
"Aruba.AP.AP300.AP377": " AP-377",
|
|
154
159
|
"Aruba.AP.AP500": " AP-5\\d\\d",
|
|
160
|
+
"Aruba.AP.AP500.AP505": " AP-505",
|
|
155
161
|
"Aruba.AP.AP500.AP514": " AP-514",
|
|
156
162
|
"Aruba.AP.AP500.AP515": " AP-515",
|
|
163
|
+
"Aruba.AP.AP500.AP535": " AP-535",
|
|
164
|
+
"Aruba.AP.AP500.AP565": " AP-565",
|
|
165
|
+
"Aruba.AP.AP500.AP567": " AP-567",
|
|
157
166
|
"Aruba.AP.AP600": " AP-6\\d\\d",
|
|
158
167
|
"Aruba.AP.AP600.AP615": " AP-615",
|
|
159
168
|
"Aruba.AP.AP600.AP635": " AP-635",
|
|
@@ -178,4 +187,4 @@
|
|
|
178
187
|
"B4com.CS4132U": "^[Bb]4com B4T-CS4132U.*",
|
|
179
188
|
"B4com.CS4148Q": "^[Bb]4com B4T-CS4148Q.*",
|
|
180
189
|
"B4com.CS4164U": "^[Bb]4com B4T-CS4164U.*"
|
|
181
|
-
}
|
|
190
|
+
}
|
|
@@ -259,38 +259,19 @@ def _old_new_per_device(ctx: OldNewDeviceContext, device: Device, filterer: Filt
|
|
|
259
259
|
|
|
260
260
|
entire_results = res.entire_results
|
|
261
261
|
json_fragment_results = res.json_fragment_results
|
|
262
|
-
old_json_fragment_files = old_files.json_fragment_files
|
|
263
262
|
|
|
264
263
|
new_files = res.new_files()
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
for file_name in new_json_fragment_files:
|
|
273
|
-
if new_json_fragment_files.get(file_name) is not None:
|
|
274
|
-
new_json_fragment_files = _update_json_config(
|
|
275
|
-
new_json_fragment_files,
|
|
276
|
-
file_name,
|
|
277
|
-
jsontools.apply_acl_filters(new_json_fragment_files[file_name][0], filters)
|
|
278
|
-
)
|
|
279
|
-
for file_name in old_json_fragment_files:
|
|
280
|
-
if old_json_fragment_files.get(file_name) is not None:
|
|
281
|
-
old_json_fragment_files[file_name] = jsontools.apply_acl_filters(old_json_fragment_files[file_name], filters)
|
|
264
|
+
|
|
265
|
+
filters = None
|
|
266
|
+
if filters_text := build_filter_text(filterer, device, ctx.stdin, ctx.args, ctx.config):
|
|
267
|
+
filters = filters_text.removesuffix("\n").split("\n")
|
|
268
|
+
|
|
269
|
+
old_json_fragment_files = old_files.json_fragment_files.copy()
|
|
270
|
+
new_json_fragment_files = res.new_json_fragment_files(old_json_fragment_files, filters=filters)
|
|
282
271
|
|
|
283
272
|
if ctx.args.acl_safe:
|
|
284
273
|
safe_new_files = res.new_files(safe=True)
|
|
285
|
-
safe_new_json_fragment_files = res.new_json_fragment_files(old_json_fragment_files, safe=True)
|
|
286
|
-
if filters:
|
|
287
|
-
for file_name in safe_new_json_fragment_files:
|
|
288
|
-
if safe_new_json_fragment_files.get(file_name):
|
|
289
|
-
safe_new_json_fragment_files = _update_json_config(
|
|
290
|
-
safe_new_json_fragment_files,
|
|
291
|
-
file_name,
|
|
292
|
-
jsontools.apply_acl_filters(safe_new_json_fragment_files[file_name][0], filters)
|
|
293
|
-
)
|
|
274
|
+
safe_new_json_fragment_files = res.new_json_fragment_files(old_json_fragment_files, safe=True, filters=filters)
|
|
294
275
|
|
|
295
276
|
if ctx.args.profile:
|
|
296
277
|
perf = res.perf_mesures()
|
|
@@ -322,13 +303,6 @@ def _old_new_per_device(ctx: OldNewDeviceContext, device: Device, filterer: Filt
|
|
|
322
303
|
)
|
|
323
304
|
|
|
324
305
|
|
|
325
|
-
def _update_json_config(json_files, file_name, new_config):
|
|
326
|
-
file = list(json_files[file_name])
|
|
327
|
-
file[0] = new_config
|
|
328
|
-
json_files[file_name] = tuple(file)
|
|
329
|
-
return json_files
|
|
330
|
-
|
|
331
|
-
|
|
332
306
|
@dataclasses.dataclass
|
|
333
307
|
class DeviceDownloadedFiles:
|
|
334
308
|
# map file path to file content for entire generators
|
|
@@ -4,9 +4,11 @@ import textwrap
|
|
|
4
4
|
from collections import OrderedDict as odict
|
|
5
5
|
from typing import (
|
|
6
6
|
Any,
|
|
7
|
+
Callable,
|
|
7
8
|
Dict,
|
|
8
9
|
Optional,
|
|
9
|
-
|
|
10
|
+
Sequence,
|
|
11
|
+
Tuple,
|
|
10
12
|
)
|
|
11
13
|
|
|
12
14
|
from annet.annlib import jsontools
|
|
@@ -84,6 +86,7 @@ class RunGeneratorResult:
|
|
|
84
86
|
self,
|
|
85
87
|
old_files: Dict[str, Optional[str]],
|
|
86
88
|
safe: bool = False,
|
|
89
|
+
filters: Sequence[str] | None = None,
|
|
87
90
|
) -> Dict[str, Tuple[Any, Optional[str]]]:
|
|
88
91
|
# TODO: safe
|
|
89
92
|
files: Dict[str, Tuple[Any, Optional[str]]] = {}
|
|
@@ -101,9 +104,9 @@ class RunGeneratorResult:
|
|
|
101
104
|
previous_config: Dict[str, Any] = files[filepath][0]
|
|
102
105
|
new_fragment = generator_result.config
|
|
103
106
|
new_config = jsontools.apply_json_fragment(
|
|
104
|
-
previous_config,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
previous_config, new_fragment,
|
|
108
|
+
acl=result_acl,
|
|
109
|
+
filters=filters,
|
|
107
110
|
)
|
|
108
111
|
if jsontools.format_json(new_config) == jsontools.format_json(previous_config):
|
|
109
112
|
# config is not changed, deprioritize reload_cmd
|
|
@@ -63,6 +63,19 @@ def _implicit_tree(device):
|
|
|
63
63
|
undo user-password complexity-check
|
|
64
64
|
netconf
|
|
65
65
|
"""
|
|
66
|
+
elif device.hw.Huawei.Quidway.S5700.S5735I:
|
|
67
|
+
text = """
|
|
68
|
+
!interface *
|
|
69
|
+
port link-type access
|
|
70
|
+
interface NULL0
|
|
71
|
+
"""
|
|
72
|
+
elif device.hw.Huawei.Quidway.S2x:
|
|
73
|
+
text = """
|
|
74
|
+
!interface *
|
|
75
|
+
port link-type hybrid
|
|
76
|
+
dot1x enable
|
|
77
|
+
interface NULL0
|
|
78
|
+
"""
|
|
66
79
|
else:
|
|
67
80
|
text = """
|
|
68
81
|
stp mode mstp
|
|
@@ -158,10 +171,14 @@ def _implicit_tree(device):
|
|
|
158
171
|
"""
|
|
159
172
|
if device.hw.Cisco.Catalyst:
|
|
160
173
|
# this configuration is not visible in running-config when enabled
|
|
174
|
+
# no vstack and system mtu are default values
|
|
161
175
|
text += r"""
|
|
162
176
|
# line console aaa config
|
|
163
177
|
!line con 0
|
|
164
178
|
authorization exec default
|
|
179
|
+
no vstack
|
|
180
|
+
system mtu routing 1500
|
|
181
|
+
system mtu jumbo 9000
|
|
165
182
|
"""
|
|
166
183
|
return parse_text(text)
|
|
167
184
|
|
|
@@ -428,6 +428,12 @@ isis *
|
|
|
428
428
|
|
|
429
429
|
error-down auto-recovery cause link-flap
|
|
430
430
|
|
|
431
|
+
configuration file auto-save backup-to-server server
|
|
432
|
+
configuration file auto-save
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
set save-configuration backup-to-server *
|
|
436
|
+
set save-configuration *
|
|
431
437
|
|
|
432
438
|
ip route-static default-bfd
|
|
433
439
|
ipv6 route-static default-bfd
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|