From 16562bc78c4236b1073923b4856fc72fe9f72416 Mon Sep 17 00:00:00 2001 From: Meline Sieber Date: Mon, 17 May 2021 08:51:02 +0200 Subject: [PATCH 1/2] update readme --- README.md | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index cdd6818..fdf394a 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,34 @@ pre-defined test cases. Such a single test case might be "can host A reach neigh This is what nuts tries to achieve: Apply test cases based on your pre-defined network topology to your actual network and have the tests confirm the correct state. +## Installation Instructions + +### Using pip + +Run `pip install nuts` + +### Using poetry + +Nuts uses [poetry](https://python-poetry.org/) as a dependency manager. + +1. [Install poetry](https://python-poetry.org/docs/#installation). +2. Clone this repository. +3. Run `$ poetry install` + +## How It Works: Test Bundles and Test Definitions + The project relies on the [pytest framework](https://docs.pytest.org/) to setup and execute the tests. Nuts itself is written as a custom pytest plugin. In the background, [nornir](https://nornir.readthedocs.io/) executes specific network tasks for the actual tests. -Additionally, nuts treats the test definition and the so-called test bundle as separate entities. The *test definition* is modeled as a custom `pytest.Class`, and a predefined set of test definitions can be found in the module `base_tests`. New test definitions can be added easily by the user of the plugin. +Nuts treats the test definition and the so-called test bundle as separate entities. The *test definition* is modeled as a custom `pytest.Class`, and a predefined set of test definitions can be found in the nuts module `base_tests`. New test definitions can be added easily by the user of the plugin. The *test bundle* is a file that is parsed by pytest. The file provides data on the desired network state and describes which test definitions should be collected and executed by pytest. The structure of the test bundle should enable people without in-depth python knowledge to add new test bundles or update existing ones to reflect changes in the network. While the readme here is only a short overview, find the [documentation of nuts on readthedocs](https://nuts.readthedocs.io/en/latest/). -## Test bundle structure +### Test Bundle Structure Currently only yaml files are supported as test bundles, but other sources such as other file formats or database entries can be considered in later nuts versions. @@ -42,7 +58,7 @@ Each test bundle contains the following structure: ``` `test_module`: The full path of the python module that contains the test class to be used. This value is optional if the test class is registered in `index.py` of the pytest-nuts plugin. -Note that it can be relevant in which directory `pytest` is started if local test modules are used. +Note that it can be relevant in which directory `pytest` is started if local test modules are used. Using `test_modules` allows you to write your own test classes. **Note: We currently do not support self-written test modules, since upcoming refactorings might introduce breaking changes.** `test_class`: The name of the python class which contains the tests that should be executed. Note that currently every test in this class will be executed. @@ -58,7 +74,7 @@ This allows the additional `max_drop` parameter in `test_execution`, since it is `test_data`: Data that is used to parametrize the tests in the test class which have the `pytest.mark.nuts` annotation. It is additionally part of the `nuts_parameters` property. -### Examples +### Example: CDP Neighbors Example of a test bundle for `TestNetmikoCdpNeighbors` which tests that `R1` is a CDP Neighbor of both `R2` and `R3`. This example creates three different tests, one for each entry in the `test_data` list. @@ -85,14 +101,7 @@ This example creates three different tests, one for each entry in the `test_data ... ``` -## Manual installation instructions -Nuts uses [poetry](https://python-poetry.org/) as a dependency manager. - -1. [Install poetry](https://python-poetry.org/docs/#installation). -2. Clone this repository. -3. Run `$ poetry install` - -## Technical Overview +### How the Test Bundle Is Converted to a Pytest Test When nuts is executed, pytest converts the test bundles (the yaml files) into tests. During test collection, the custom pytest marker `nuts` uses the data that has been defined in the test bundle mentioned above. This annotation is a wrapper around the `pytest.mark.parametrize` annotation and allows the plugin to use the data entries from the test bundle. For each entry in the `test_data` section of the test bundle, the custom marker generates a single test case. To achieve this, the plugin transforms the entries into n-tuples, since `pytest.mark.parametrize` expects a list of n-tuples as input. @@ -102,18 +111,16 @@ For each entry in `test_data` these fields are extracted and transformed to a tu If any of these fields are not present in an entry of `test_data`, the corresponding test case will be skipped. A second argument determines optional fields that can also be used in a test case as well - non-present values are passed into the function as `None`. -#### Example of a test class with custom marker +The following test-run of CDP neighbors for example checks the local port: ```python -@pytest.mark.usefixtures("check_nuts_result") # see below +@pytest.mark.usefixtures("check_nuts_result") class TestNetmikoCdpNeighbors: @pytest.mark.nuts("host,remote_host,local_port") def test_local_port(self, single_result, remote_host, local_port): assert single_result.result[remote_host]["local_port"] == local_port ``` -This test-run of CDP neighbors checks the local port. - Before each test evaluation, the fixture `@pytest.mark.usefixtures("check_nuts_result")` checks the result of the network information that has been gathered by nornir in the background: It asserts that that no exception was thrown while doing so. The required fields are `host`, `remote_host` and `local_port` - they must be present in the custom marker, @@ -126,15 +133,15 @@ Each test module implements a context class to provide module-specific functiona This guarantees a consistent interface across all tests for test setup and execution. Currently, the predefined test classes use [nornir](https://nornir.readthedocs.io/en/latest/) in order to communicate with the network devices, therefore the test classes derive all from a more specific `NornirNutsContext`, -which provides a nornir instance and nornir-specific helpers. +which provides a nornir instance and nornir-specific helpers. In the example above, it is a class called `CdpNeighborsContext` that derives from `NornirNutsContext`. -## Development +## Develop Your Own Test Classes Nuts is essentially designed as a pytest-plugin and it is possible to add your own, self-written test classes. -A dev documentation on how to write your own test classes is planned for the future. -Until then, please read the regular [documentation of nuts](https://nuts.readthedocs.io/en/latest/) on how to use it. +A dev documentation on how to write your own test classes is planned for a future release. +Still, it is possible to write your own test classes nevertheless, even if we cannot guarantee that upcoming planned refactorings do not introduce breaking changes. # Thanks * [Matthias Gabriel](https://github.com/MatthiasGabriel), who laid the foundations of nuts. -* [Florian Bruhin](https://github.com/The-Compiler) for invaluable feedback. \ No newline at end of file +* [Florian Bruhin (The Compiler)](https://github.com/The-Compiler) for invaluable feedback and advice. \ No newline at end of file From 137c94cd01798f00c0a46c264f3bdd306fe72623 Mon Sep 17 00:00:00 2001 From: Meline Sieber Date: Mon, 17 May 2021 10:12:27 +0200 Subject: [PATCH 2/2] update doc --- README.md | 8 +- docs/source/conf.py | 7 +- docs/source/dev/index.rst | 6 - docs/source/index.rst | 46 +++-- .../installation/{index.rst => install.rst} | 30 ++- docs/source/testbundles/alltestbundles.rst | 2 +- docs/source/tutorial/firststeps.rst | 45 +++-- poetry.lock | 177 ++++++++---------- 8 files changed, 161 insertions(+), 160 deletions(-) delete mode 100644 docs/source/dev/index.rst rename docs/source/installation/{index.rst => install.rst} (66%) diff --git a/README.md b/README.md index fdf394a..03f85fa 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Introduction -The NetTowel Network Unit Testing System or "nuts" in short is the testing component of the NetTowel Project. +The NetTowel Network Unit Testing System or "nuts" in short is the testing component of the NetTowel Project, which is developed at the Institute of Networked Solutions in Rapperswil, Switzerland. It draws on the concept of unit tests, known from the domain of programming, and applies it to the domain of networking. One major difference between unit tests in programming and @@ -132,13 +132,15 @@ but also be provided as argument to the test method itself. Each test module implements a context class to provide module-specific functionality to its tests. This context class is a `NutsContext` or a subclass of it. This guarantees a consistent interface across all tests for test setup and execution. Currently, the predefined test classes use [nornir](https://nornir.readthedocs.io/en/latest/) in order to communicate -with the network devices, therefore the test classes derive all from a more specific `NornirNutsContext`, +with the network devices. Those test classes derive all from a more specific `NornirNutsContext`, which provides a nornir instance and nornir-specific helpers. In the example above, it is a class called `CdpNeighborsContext` that derives from `NornirNutsContext`. +If you want to learn more how nuts works but do not have a running network in the background, there's a nuts showcase - an offline test class that displays the basic functionality of nuts. See the [tutorial](https://nuts.readthedocs.io/en/latest/tutorial/firststeps.html) for further information. + ## Develop Your Own Test Classes Nuts is essentially designed as a pytest-plugin and it is possible to add your own, self-written test classes. -A dev documentation on how to write your own test classes is planned for a future release. +A dev documentation on how to write your own test classes is planned for a future release. Still, it is possible to write your own test classes nevertheless, even if we cannot guarantee that upcoming planned refactorings do not introduce breaking changes. # Thanks diff --git a/docs/source/conf.py b/docs/source/conf.py index 0cf8f06..2920525 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,6 +12,7 @@ # import os import sys +import datetime sys.path.insert(0, os.path.abspath("../..")) sys.setrecursionlimit(1500) @@ -19,11 +20,11 @@ # -- Project information ----------------------------------------------------- project = "NUTS" -copyright = "2020, Matthias Gabriel, Méline Sieber, Urs Baumann" -author = "Matthias Gabriel, Méline Sieber, Urs Baumann" +copyright = f"{datetime.date.today().year}, Méline Sieber, Urs Baumann" +author = "Méline Sieber" # The full version, including alpha/beta/rc tags -release = "0.1.0" +release = "1.0.0" # -- General configuration --------------------------------------------------- diff --git a/docs/source/dev/index.rst b/docs/source/dev/index.rst deleted file mode 100644 index e3955c2..0000000 --- a/docs/source/dev/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -How to enhance NUTS -=================== - -.. todo:: - - Include more technical details on how NUTS is structured. diff --git a/docs/source/index.rst b/docs/source/index.rst index b537ab2..33c2f57 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -6,41 +6,40 @@ Documentation of NUTS Introduction ------------ -The NetTowel Network Unit Testing System or "NUTS" for short is the -testing component of the NetTowel Project, which is developed at the Institute of Networked Solutions in Rapperswil, Switzerland. -NUTS draws on the concept of unit tests, known from the domain of -software development, and applies it to the domain of networking. - -One major difference between unit tests in software development and -network tests is the definition of a test. -In software development, unit tests normally focus on testing edge cases, -since the amount of non-edge cases is not definable. -In the network testing domain, tests are less about edge cases, but more about testing network functionalities with pre-defined test cases. Such a single test case might be "can host A -reach neighbors X, Y, Z?" or "has host A all BGP neighbors configured correctly?" on many different devices. - -This is what NUTS tries to achieve: -Use pre-defined test cases together with your network topology, apply this to your actual network and have the tests confirm that the network has the expected functionalities. - -How NUTS works +The NetTowel Network Unit Testing System or "nuts" in short is the testing component of the NetTowel Project, which is developed at the Institute of Networked Solutions in Rapperswil, Switzerland. +It draws on the concept of unit tests, known from the domain of programming, and applies it to the domain of networking. + +One major difference between unit tests in programming and +network tests is the definition of what a test actually is. +In programming, unit tests normally focus on testing edge cases, +since the amount of non-edge cases is not definable. +In the network testing domain, tests are less about edge cases, but more about testing existing network states with +pre-defined test cases. Such a single test case might be "can host A reach neighbors X, Y, Z?" on many different devices. +This is what nuts tries to achieve: +Apply test cases based on your pre-defined network topology to your actual network and have the tests confirm the correct state. + +How nuts works -------------- -In order to run NUTS, two components are required: +In order to run nuts, two components are required: #. **Inventory of the network**. Currently, these are YAML-files in the form of a `nornir inventory `__. They contain all details of your network, such as hosts, login-information and other configuration. #. **Test bundles** in the form of YAML-files that specify the actual tests. A test bundle is a series of tests that are logically related to each other. Each test bundle is structured in a similar way, but has specific fields tailored to the test bundle. Some field values in a test bundle are directly related to your inventory. -Head over to the :doc:`Usage section ` to see how those two components are structured and how you get NUTS up and running. +Head over to the :doc:`Usage section ` to see how those two components are structured and how you get nuts up and running. The project relies on the `pytest framework `__ to setup and execute the -tests. NUTS itself is written as a custom pytest plugin. In the background, `nornir `__ executes specific network tasks for the actual tests. +tests. Nuts itself is written as a custom pytest plugin. In the background, `nornir `__ executes specific network tasks for the actual tests. -Pytest reads in the test bundle (2.) and transforms it into test runs. In the background, nornir uses the network information provided in the inventory (1.), queries the network based on the specific test bundle and passes the results of those queries to pytest. Pytest then evaluates if the expectations defined in the test bundle match those results. +Pytest reads in the test bundle (step 2 above) and transforms it into test runs. In the background, nornir uses the network information provided in the inventory (step 1 above), queries the network based on the specific test bundle and passes the results of those queries to pytest. Pytest then evaluates if the expectations defined in the test bundle match those results. -Enhance NUTS +Enhance nuts ------------ -Since NUTS is written as a pytest plugin and in python, you can customize it yourself and write your own test classes. Please see the :doc:`development section ` to see how NUTS is structured and how to write your own test classes. +Nuts is written in python and designed as a pytest plugin. It provides some base tests described in :doc:`the section about all test bundles `, but since it's a plugin, you can write your own, self-written test classes for your custom tests. +A dev documentation on how to write your own test classes is planned for a future release. +We do not support self-written tests at the moment, since planned refactorings might introduce breaking changes. Still, you can already write your own test classes - see the ``nuts/base_tests`` folder in the code repository to learn how test classes are written. Contents ======== @@ -49,10 +48,9 @@ Contents :maxdepth: 2 Home - Installation + Installation Tutorial Test Bundles - Development Indices and tables diff --git a/docs/source/installation/index.rst b/docs/source/installation/install.rst similarity index 66% rename from docs/source/installation/index.rst rename to docs/source/installation/install.rst index 121a31d..c2ee7d5 100644 --- a/docs/source/installation/index.rst +++ b/docs/source/installation/install.rst @@ -4,29 +4,25 @@ Installation of NUTS Installation Instructions ------------------------- -NUTS is currently not published on the Python Package Index (`PyPI `_). It has to be cloned and installed manually. +Nuts requires Python 3.7 or higher. -.. todo:: - - Use public repository to access code and retest the installation instructions. - -.. code:: shell +Installation via pip +.................... - git clone +NUTS is published on the Python Package Index (`PyPI `_), therefore you can install nuts using ``pip``: - cd nettowel-nuts +.. code:: shell - # create virtual environment - python -m venv .venv + pip install nuts - # activate virtual environment - source .venv/bin/activate +Installation via poetry +....................... - # install NUTS - pip install +Nuts uses `poetry `__ as a dependency manager. - # install NUTS directly from git without clone first - pip install git+https://github.com/INSRapperswil/Nuts.git +1. `Install poetry `__. +2. Clone the `nuts repository `__ +3. Run ``$ poetry install`` Parsing with ntc-templates -------------------------- @@ -54,7 +50,7 @@ Deinstallation .. code:: shell - pip uninstall nettowel-nuts + pip uninstall nuts If you installed everything in a virtual environment, you can delete the folder that contains the virtual environment. diff --git a/docs/source/testbundles/alltestbundles.rst b/docs/source/testbundles/alltestbundles.rst index ef4765e..6061b16 100644 --- a/docs/source/testbundles/alltestbundles.rst +++ b/docs/source/testbundles/alltestbundles.rst @@ -5,7 +5,7 @@ A test bundle contains one ore more tests that are logically related to each oth This section contains all test bundles which have been implemented in NUTS, you can incorporate them in your own bundles. They can be executed with the command ``$ pytest .yaml`` from your project root. -Note that you need an inventory for the tests to work. Please see :doc:`First Steps with NUTS <../tutorial/firststeps>` for more information. +Note that you need an inventory of network devices for the tests to work. Please see :doc:`First Steps with NUTS <../tutorial/firststeps>` for more information. In some test bundles you can directly pass arguments to the nornir task, i.e. the network query that is executed in the background. For those test bundles we indicate the specific task which is used to query the devices, so that you can look up all available arguments. diff --git a/docs/source/tutorial/firststeps.rst b/docs/source/tutorial/firststeps.rst index 7f2fbf6..d7d603e 100644 --- a/docs/source/tutorial/firststeps.rst +++ b/docs/source/tutorial/firststeps.rst @@ -1,14 +1,14 @@ First Steps with NUTS ===================== -This tutorial guides you through a minimal setup of the NetTowel Unit Testing System (NUTS, or nuts). +This tutorial guides you through a minimal setup of the NetTowel Unit Testing System (NUTS, or nuts). A showcase is included in nuts' code that allows you to learn the basic mechanics of nuts without the need of an actual network -- find those details at the end of this tutorial. Two major components are needed for nuts: #. A network inventory #. Test bundles -Here's an overview on how to organise your files so that NUTS can find everything it needs. The root folder also contains the virtual environment with the :doc:`NUTS installation <../installation/index>`. +Here's an overview on how to organise your files so that NUTS can find everything it needs. The root folder also contains the virtual environment with the :doc:`nuts installation <../installation/install>`. .. code:: shell @@ -22,7 +22,7 @@ Here's an overview on how to organise your files so that NUTS can find everythin 1. Network Inventory -------------------- -You must provide information on your network configuration so that NUTS can actually interact with it. Currently, NUTS uses a `nornir inventory `__ and ``nr-config.yaml`` which uses that inventory. +You must provide information on your network configuration so that nuts can actually interact with it. Currently, NUTS uses a `nornir inventory `__ and ``nr-config.yaml`` which uses that inventory. A sample ``hosts.yaml`` might look like this: @@ -69,9 +69,9 @@ If you set up the above folders and files, you're ready to write test bundles. 2. Test Bundle -------------- -A test bundle is a collection of tests are logically related to each other, for example tests that all revolve around "information on BGP neighbors". The test bundle describes which test definition should be collected and executed and provides data for those tests. The bundles are written as individual entries in a YAML file. +A test bundle is a collection of tests that are logically related to each other, for example tests that all revolve around "information on BGP neighbors". The test bundle describes which test definition should be collected and executed and provides data for those tests. The bundles are written as individual entries in a YAML file. -Currently only YAML files are supported as test bundle format, but other data sources could be integrated in later versions of nuts. +Currently only YAML files are supported as test bundle format, but other data sources could be integrated in later versions of nuts. Structure of a Test Bundle ************************** @@ -86,7 +86,7 @@ Each test bundle contains the following structure: test_execution: # optional test_data: -``test_module``: Optional. The full path of the python module that contains the test class to be used. This value is optional if the test class is registered in ``index.py`` of the pytest-nuts plugin. Note that it can be relevant in which directory ``pytest`` is started if local test modules are used. +``test_module``: Optional. The full path of the python module that contains the test class to be used. This value is optional if the test class is registered in ``index.py`` of the pytest-nuts plugin. Note that it can be relevant in which directory ``pytest`` is started if local test modules are used. Using ``test_modules`` allows you to write your own test classes. **Note: We currently do not support self-written test modules, since upcoming refactorings might introduce breaking changes.** ``test_class``: Required. The name of the python class which contains the tests that should be executed. Note that currently every test in this class is executed. @@ -124,12 +124,7 @@ Notes: * ``test_data.max_drop: 1``. Maximum one ping attempt is allowed to fail to still count as SUCCESS ping. -We save this file as ``test-definition-ping.yaml`` into the ``tests`` folder. - -Run NUTS --------- - -If everything is set up as shown above, run the test from the root folder: +We save this file as ``test-definition-ping.yaml`` into the ``tests`` folder. If everything is set up as shown above, run the test from the root folder: .. code:: shell @@ -137,3 +132,29 @@ If everything is set up as shown above, run the test from the root folder: Pytest's output should then inform you if the test succeeded or not. + +Sample Test-Bundle Without a Network +************************************ + +The sample test bundle above requires a network inventory and a running network in the background. In case you want to learn how nuts works but do not have a network at hand, nuts comes with an offline showcase to display its functionality. Use it as follows: + +#. Clone the `nuts repository `__ and change into the cloned folder. +#. Create a `virtual environment (venv) `__ in it and activate it. +#. Install nuts in the venv. +#. Run the showcase test bundle. + +.. code:: shell + + $ git clone https://github.com/INSRapperswil/nuts && cd nuts + $ python -m venv .venv && source .venv/bin/activate + $ pip install . + $ pytest tests/showcase_test/test-expanse.yaml + +How it works: Each test module implements a context class to provide module-specific functionality to its tests. This context class is a ``NutsContext`` or a subclass of it. This guarantees a consistent interface across all tests for test setup and execution. + +The predefined test classes which depend on a network all use `nornir `__ in order to communicate with the network devices. Those test classes all derive all from a more specific ``NornirNutsContext``, which provides a nornir instance and nornir-specific helpers. + +In order for the offline showcase to work, the test class derives from ``NutsContext`` and implements its own context class. See the code in ``nuts/tests/showcase/showcase_expanse.py`` to see the structure of this offline context class. + + + diff --git a/poetry.lock b/poetry.lock index 39f54cf..8bfbf71 100644 --- a/poetry.lock +++ b/poetry.lock @@ -16,17 +16,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "20.3.0" +version = "21.2.0" description = "Classes Without Boilerplate" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"] -docs = ["furo", "sphinx", "zope.interface"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] [[package]] name = "bcrypt" @@ -108,11 +108,14 @@ passlib = "*" [[package]] name = "click" -version = "7.1.2" +version = "8.0.0" description = "Composable command line interface toolkit" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" @@ -130,6 +133,9 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +[package.dependencies] +toml = {version = "*", optional = true, markers = "extra == \"toml\""} + [package.extras] toml = ["toml"] @@ -209,30 +215,30 @@ python-versions = "*" [[package]] name = "jinja2" -version = "2.11.3" +version = "3.0.0" description = "A very fast and expressive template engine." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" [package.dependencies] -MarkupSafe = ">=0.23" +MarkupSafe = ">=2.0.0rc2" [package.extras] -i18n = ["Babel (>=0.8)"] +i18n = ["Babel (>=2.7)"] [[package]] name = "junos-eznc" -version = "2.6.0" +version = "2.5.4" description = "Junos 'EZ' automation for non-programmers" category = "main" optional = false -python-versions = ">=3.*, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] jinja2 = ">=2.7.1" lxml = ">=3.2.4" -ncclient = "0.6.9" +ncclient = ">=0.6.3" netaddr = "*" paramiko = ">=1.15.2" pyparsing = "*" @@ -259,11 +265,11 @@ source = ["Cython (>=0.29.7)"] [[package]] name = "markupsafe" -version = "1.1.1" +version = "2.0.0" description = "Safely add untrusted strings to HTML/XML markup." category = "main" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +python-versions = ">=3.6" [[package]] name = "mypy-extensions" @@ -275,7 +281,7 @@ python-versions = "*" [[package]] name = "napalm" -version = "3.2.0" +version = "3.3.0" description = "Network Automation and Programmability Abstraction Layer with Multivendor support" category = "main" optional = false @@ -288,6 +294,7 @@ future = "*" jinja2 = "*" junos-eznc = ">=2.2.1" lxml = ">=4.3.0" +ncclient = "*" netaddr = "*" netmiko = ">=3.1.0" paramiko = ">=2.6.0" @@ -532,7 +539,7 @@ cp2110 = ["hidapi"] [[package]] name = "pytest" -version = "6.2.3" +version = "6.2.4" description = "pytest: simple powerful testing with Python" category = "main" optional = false @@ -554,14 +561,14 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm [[package]] name = "pytest-cov" -version = "2.11.1" +version = "2.12.0" description = "Pytest plugin for measuring coverage." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.dependencies] -coverage = ">=5.2.1" +coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" [package.extras] @@ -637,7 +644,7 @@ paramiko = "*" [[package]] name = "six" -version = "1.15.0" +version = "1.16.0" description = "Python 2 and 3 compatibility utilities" category = "main" optional = false @@ -702,7 +709,7 @@ python-versions = "*" [[package]] name = "typing-extensions" -version = "3.7.4.3" +version = "3.10.0.0" description = "Backported and Experimental Type Hints for Python 3.5+" category = "main" optional = false @@ -759,8 +766,8 @@ atomicwrites = [ {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ - {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, - {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, + {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, + {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, ] bcrypt = [ {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"}, @@ -826,8 +833,8 @@ ciscoconfparse = [ {file = "ciscoconfparse-1.5.30.tar.gz", hash = "sha256:e3c9ad5ff7563c6d3b4542d2826f4b07feb0e46ea5c698886ab8c4d55cc28815"}, ] click = [ - {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, - {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, + {file = "click-8.0.0-py3-none-any.whl", hash = "sha256:e90e62ced43dc8105fb9a26d62f0d9340b5c8db053a814e25d95c19873ae87db"}, + {file = "click-8.0.0.tar.gz", hash = "sha256:7d8c289ee437bcb0316820ccee14aefcb056e58d31830ecab8e47eda6540e136"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -921,12 +928,12 @@ iniconfig = [ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] jinja2 = [ - {file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"}, - {file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"}, + {file = "Jinja2-3.0.0-py3-none-any.whl", hash = "sha256:2f2de5285cf37f33d33ecd4a9080b75c87cd0c1994d5a9c6df17131ea1f049c6"}, + {file = "Jinja2-3.0.0.tar.gz", hash = "sha256:ea8d7dd814ce9df6de6a761ec7f1cac98afe305b8cdc4aaae4e114b8d8ce24c5"}, ] junos-eznc = [ - {file = "junos-eznc-2.6.0.tar.gz", hash = "sha256:761a85a1485f8dc41b983ae7296889c7a78394b78d2de68f0831b7efa5f6ca34"}, - {file = "junos_eznc-2.6.0-py2.py3-none-any.whl", hash = "sha256:598c3569b21f362f0bad626ad3756f9f8a3f4d507a0ff37ff76e33b3ed73859e"}, + {file = "junos-eznc-2.5.4.tar.gz", hash = "sha256:bf036d0af9ee5c5e4f517cb5fc902fe891fa120e18f459805862c53d4a97193a"}, + {file = "junos_eznc-2.5.4-py2.py3-none-any.whl", hash = "sha256:e05c36d56d8b8d13b1fb3bb763828bb3ee80fa1dcadc3a6762e8e2568504676d"}, ] lxml = [ {file = "lxml-4.6.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2"}, @@ -967,66 +974,48 @@ lxml = [ {file = "lxml-4.6.3.tar.gz", hash = "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468"}, ] markupsafe = [ - {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, - {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, - {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-win32.whl", hash = "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39"}, - {file = "MarkupSafe-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8"}, - {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2efaeb1baff547063bad2b2893a8f5e9c459c4624e1a96644bbba08910ae34e0"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:441ce2a8c17683d97e06447fcbccbdb057cbf587c78eb75ae43ea7858042fe2c"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:45535241baa0fc0ba2a43961a1ac7562ca3257f46c4c3e9c0de38b722be41bd1"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:90053234a6479738fd40d155268af631c7fca33365f964f2208867da1349294b"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3b54a9c68995ef4164567e2cd1a5e16db5dac30b2a50c39c82db8d4afaf14f63"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f58b5ba13a5689ca8317b98439fccfbcc673acaaf8241c1869ceea40f5d585bf"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-win32.whl", hash = "sha256:a00dce2d96587651ef4fa192c17e039e8cfab63087c67e7d263a5533c7dad715"}, + {file = "MarkupSafe-2.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:007dc055dbce5b1104876acee177dbfd18757e19d562cd440182e1f492e96b95"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a08cd07d3c3c17cd33d9e66ea9dee8f8fc1c48e2d11bd88fd2dc515a602c709b"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3c352ff634e289061711608f5e474ec38dbaa21e3e168820d53d5f4015e5b91b"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:32200f562daaab472921a11cbb63780f1654552ae49518196fc361ed8e12e901"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:fef86115fdad7ae774720d7103aa776144cf9b66673b4afa9bcaa7af990ed07b"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e79212d09fc0e224d20b43ad44bb0a0a3416d1e04cf6b45fed265114a5d43d20"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:79b2ae94fa991be023832e6bcc00f41dbc8e5fe9d997a02db965831402551730"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-win32.whl", hash = "sha256:3261fae28155e5c8634dd7710635fe540a05b58f160cef7713c7700cb9980e66"}, + {file = "MarkupSafe-2.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e4570d16f88c7f3032ed909dc9e905a17da14a1c4cfd92608e3fda4cb1208bbd"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f806bfd0f218477d7c46a11d3e52dc7f5fdfaa981b18202b7dc84bbc287463b"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e77e4b983e2441aff0c0d07ee711110c106b625f440292dfe02a2f60c8218bd6"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:031bf79a27d1c42f69c276d6221172417b47cb4b31cdc73d362a9bf5a1889b9f"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:83cf0228b2f694dcdba1374d5312f2277269d798e65f40344964f642935feac1"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4cc563836f13c57f1473bc02d1e01fc37bab70ad4ee6be297d58c1d66bc819bf"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d00a669e4a5bec3ee6dbeeeedd82a405ced19f8aeefb109a012ea88a45afff96"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-win32.whl", hash = "sha256:161d575fa49395860b75da5135162481768b11208490d5a2143ae6785123e77d"}, + {file = "MarkupSafe-2.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:58bc9fce3e1557d463ef5cee05391a05745fd95ed660f23c1742c711712c0abb"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fb47f97f1d338b943126e90b79cad50d4fcfa0b80637b5a9f468941dbbd9ce5"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dab0c685f21f4a6c95bfc2afd1e7eae0033b403dd3d8c1b6d13a652ada75b348"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:664832fb88b8162268928df233f4b12a144a0c78b01d38b81bdcf0fc96668ecb"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:df561f65049ed3556e5b52541669310e88713fdae2934845ec3606f283337958"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:24bbc3507fb6dfff663af7900a631f2aca90d5a445f272db5fc84999fa5718bc"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:87de598edfa2230ff274c4de7fcf24c73ffd96208c8e1912d5d0fee459767d75"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a19d39b02a24d3082856a5b06490b714a9d4179321225bbf22809ff1e1887cc8"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-win32.whl", hash = "sha256:4aca81a687975b35e3e80bcf9aa93fe10cd57fac37bf18b2314c186095f57e05"}, + {file = "MarkupSafe-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:70820a1c96311e02449591cbdf5cd1c6a34d5194d5b55094ab725364375c9eb2"}, + {file = "MarkupSafe-2.0.0.tar.gz", hash = "sha256:4fae0677f712ee090721d8b17f412f1cbceefbf0dc180fe91bab3232f38b4527"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] napalm = [ - {file = "napalm-3.2.0-py2.py3-none-any.whl", hash = "sha256:6ab07a8a360150198b3c33c2fa4e92a9658cda9821736d24f2399343425d2af3"}, - {file = "napalm-3.2.0.tar.gz", hash = "sha256:6e69a505f5d4a678c42f048d13153afabf10b7fec72868e3bfb53ff4089206fc"}, + {file = "napalm-3.3.0-py2.py3-none-any.whl", hash = "sha256:7708036fd17a38711643b8911c942b4bb3b59556e2806d31c4392605e2b7aa35"}, + {file = "napalm-3.3.0.tar.gz", hash = "sha256:0ac7901105fed5f67b1b6e498b0b2b008f77b72c9c1ef323059a97125753138b"}, ] ncclient = [ {file = "ncclient-0.6.10.tar.gz", hash = "sha256:67b1eba5a6c7c6075746d8c33d4e8f4ded17604034c1fcd1c78996ef52bf66ff"}, @@ -1119,12 +1108,12 @@ pyserial = [ {file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"}, ] pytest = [ - {file = "pytest-6.2.3-py3-none-any.whl", hash = "sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"}, - {file = "pytest-6.2.3.tar.gz", hash = "sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634"}, + {file = "pytest-6.2.4-py3-none-any.whl", hash = "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"}, + {file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"}, ] pytest-cov = [ - {file = "pytest-cov-2.11.1.tar.gz", hash = "sha256:359952d9d39b9f822d9d29324483e7ba04a3a17dd7d05aa6beb7ea01e359e5f7"}, - {file = "pytest_cov-2.11.1-py2.py3-none-any.whl", hash = "sha256:bdb9fdb0b85a7cc825269a4c56b48ccaa5c7e365054b6038772c32ddcdc969da"}, + {file = "pytest-cov-2.12.0.tar.gz", hash = "sha256:8535764137fecce504a49c2b742288e3d34bc09eed298ad65963616cc98fd45e"}, + {file = "pytest_cov-2.12.0-py2.py3-none-any.whl", hash = "sha256:95d4933dcbbacfa377bb60b29801daa30d90c33981ab2a79e9ab4452c165066e"}, ] pyyaml = [ {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, @@ -1238,8 +1227,8 @@ scp = [ {file = "scp-0.13.3.tar.gz", hash = "sha256:8bd748293d7362073169b96ce4b8c4f93bcc62cfc5f7e1d949e01e406a025bd4"}, ] six = [ - {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, - {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] tenacity = [ {file = "tenacity-7.0.0-py2.py3-none-any.whl", hash = "sha256:a0ce48587271515db7d3a5e700df9ae69cce98c4b57c23a4886da15243603dd8"}, @@ -1289,9 +1278,9 @@ typed-ast = [ {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, ] typing-extensions = [ - {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, - {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, - {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, + {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"}, + {file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"}, + {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"}, ] urllib3 = [ {file = "urllib3-1.26.4-py2.py3-none-any.whl", hash = "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df"},