We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`base.clitools.cl_napalm:main` entrypoint still uses PIP internals
https://github.com/napalm-automation/napalm/blob/f45fc4f8e9108cacd76ce8f5cd9182df45129480/napalm/base/clitools/cl_napalm.py#L146

Should switch to `pkg_resources.find_distributions()` or similar.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `napalm/base/clitools/cl_napalm.py`
Content:
```
1 # Python3 support
2 from __future__ import print_function
3 from __future__ import unicode_literals
4 
5 # import helpers
6 from napalm.base import get_network_driver
7 from napalm.base.clitools import helpers
8 
9 # stdlib
10 import pip
11 import json
12 import logging
13 import argparse
14 import getpass
15 from functools import wraps
16 
17 
18 def debugging(name):
19     def real_decorator(func):
20         @wraps(func)
21         def wrapper(*args, **kwargs):
22                 censor_parameters = ["password"]
23                 censored_kwargs = {k: v if k not in censor_parameters else "*******"
24                                    for k, v in kwargs.items()}
25                 logger.debug("{} - Calling with args: {}, {}".format(name, args, censored_kwargs))
26                 try:
27                     r = func(*args, **kwargs)
28                     logger.debug("{} - Successful".format(name))
29                     return r
30                 except NotImplementedError:
31                     if name not in ["pre_connection_tests", "connection_tests",
32                                     "post_connection_tests"]:
33                         logger.debug("{} - Not implemented".format(name))
34                 except Exception as e:
35                     logger.error("{} - Failed: {}".format(name, e))
36                     print("\n================= Traceback =================\n")
37                     raise
38         return wrapper
39     return real_decorator
40 
41 
42 logger = logging.getLogger('napalm')
43 
44 
45 def build_help():
46     parser = argparse.ArgumentParser(
47         description='Command line tool to handle configuration on devices using NAPALM.'
48                     'The script will print the diff on the screen',
49         epilog='Automate all the things!!!'
50     )
51     parser.add_argument(
52         dest='hostname',
53         action='store',
54         help='Host where you want to deploy the configuration.'
55     )
56     parser.add_argument(
57         '--user', '-u',
58         dest='user',
59         action='store',
60         default=getpass.getuser(),
61         help='User for authenticating to the host. Default: user running the script.'
62     )
63     parser.add_argument(
64         '--password', '-p',
65         dest='password',
66         action='store',
67         help='Password for authenticating to the host.'
68              'If you do not provide a password in the CLI you will be prompted.',
69     )
70     parser.add_argument(
71         '--vendor', '-v',
72         dest='vendor',
73         action='store',
74         required=True,
75         help='Host Operating System.'
76     )
77     parser.add_argument(
78         '--optional_args', '-o',
79         dest='optional_args',
80         action='store',
81         help='String with comma separated key=value pairs passed via optional_args to the driver.',
82     )
83     parser.add_argument(
84         '--debug',
85         dest='debug',
86         action='store_true',
87         help='Enables debug mode; more verbosity.'
88     )
89     subparser = parser.add_subparsers(title='actions')
90 
91     config = subparser.add_parser('configure', help='Perform a configuration operation')
92     config.set_defaults(which='config')
93     config.add_argument(
94         dest='config_file',
95         action='store',
96         help='File containing the configuration you want to deploy.'
97     )
98     config.add_argument(
99         '--strategy', '-s',
100         dest='strategy',
101         action='store',
102         choices=['replace', 'merge'],
103         default='replace',
104         help='Strategy to use to deploy configuration. Default: replace.'
105     )
106     config.add_argument(
107         '--dry-run', '-d',
108         dest='dry_run',
109         action='store_true',
110         default=None,
111         help='Only returns diff, it does not deploy the configuration.',
112     )
113 
114     call = subparser.add_parser('call', help='Call a napalm method')
115     call.set_defaults(which='call')
116     call.add_argument(
117         dest='method',
118         action='store',
119         help='Run this method'
120     )
121     call.add_argument(
122         '--method-kwargs', '-k',
123         dest='method_kwargs',
124         action='store',
125         help='kwargs to pass to the method. For example: "destination=1.1.1.1,protocol=bgp"'
126     )
127 
128     validate = subparser.add_parser('validate', help='Validate configuration/state')
129     validate.set_defaults(which='validate')
130     validate.add_argument(
131         dest='validation_file',
132         action='store',
133         help='Validation file containing resources derised states'
134     )
135     args = parser.parse_args()
136 
137     if args.password is None:
138         password = getpass.getpass('Enter password: ')
139         setattr(args, 'password', password)
140 
141     return args
142 
143 
144 def check_installed_packages():
145     logger.debug("Gathering napalm packages")
146     installed_packages = pip.get_installed_distributions()
147     napalm_packages = sorted(["{}=={}".format(i.key, i.version)
148                               for i in installed_packages if i.key.startswith("napalm")])
149     for n in napalm_packages:
150         logger.debug(n)
151 
152 
153 @debugging("get_network_driver")
154 def call_get_network_driver(vendor):
155     return get_network_driver(vendor)
156 
157 
158 @debugging("__init__")
159 def call_instantiating_object(driver, *args, **kwargs):
160     return driver(*args, **kwargs)
161 
162 
163 @debugging("pre_connection_tests")
164 def call_pre_connection(driver):
165     driver.pre_connection_tests()
166 
167 
168 @debugging("connection_tests")
169 def call_connection(device):
170     device.connection_tests()
171 
172 
173 @debugging("post_connection_tests")
174 def call_post_connection(device):
175     device.post_connection_tests()
176 
177 
178 @debugging("get_facts")
179 def call_facts(device):
180     facts = device.get_facts()
181     logger.debug("Gathered facts:\n{}".format(json.dumps(facts, indent=4)))
182     print(json.dumps(facts, indent=4))
183 
184 
185 @debugging("close")
186 def call_close(device):
187     return device.close()
188 
189 
190 @debugging("open")
191 def call_open_device(device):
192     return device.open()
193 
194 
195 @debugging("load_replace_candidate")
196 def call_load_replace_candidate(device, *args, **kwargs):
197     return device.load_replace_candidate(*args, **kwargs)
198 
199 
200 @debugging("load_merge_candidate")
201 def call_load_merge_candidate(device, *args, **kwargs):
202     return device.load_merge_candidate(*args, **kwargs)
203 
204 
205 @debugging("compare_config")
206 def call_compare_config(device, *args, **kwargs):
207     diff = device.compare_config(*args, **kwargs)
208     logger.debug("Gathered diff:")
209     print(diff)
210     return diff
211 
212 
213 @debugging("commit_config")
214 def call_commit_config(device, *args, **kwargs):
215     return device.commit_config(*args, **kwargs)
216 
217 
218 def configuration_change(device, config_file, strategy, dry_run):
219     if strategy == 'replace':
220         strategy_method = call_load_replace_candidate
221     elif strategy == 'merge':
222         strategy_method = call_load_merge_candidate
223 
224     strategy_method(device, filename=config_file)
225 
226     diff = call_compare_config(device)
227 
228     if not dry_run:
229         call_commit_config(device)
230     return diff
231 
232 
233 @debugging("method")
234 def call_getter(device, method, **kwargs):
235     logger.debug("{} - Attempting to resolve method".format(method))
236     func = getattr(device, method)
237     logger.debug("{} - Attempting to call method with kwargs: {}".format(method, kwargs))
238     r = func(**kwargs)
239     logger.debug("{} - Response".format(method))
240     print(json.dumps(r, indent=4))
241 
242 
243 @debugging("compliance_report")
244 def call_compliance_report(device, validation_file):
245     result = device.compliance_report(validation_file)
246     print(json.dumps(result, indent=4))
247     return result
248 
249 
250 def run_tests(args):
251     driver = call_get_network_driver(args.vendor)
252     optional_args = helpers.parse_optional_args(args.optional_args)
253 
254     device = call_instantiating_object(driver, args.hostname, args.user, password=args.password,
255                                        timeout=60, optional_args=optional_args)
256 
257     if args.debug:
258         call_pre_connection(device)
259 
260     call_open_device(device)
261 
262     if args.debug:
263         call_connection(device)
264         call_facts(device)
265 
266     if args.which == 'call':
267         method_kwargs = helpers.parse_optional_args(args.method_kwargs)
268         call_getter(device, args.method, **method_kwargs)
269     elif args.which == 'config':
270         configuration_change(device, args.config_file, args.strategy, args.dry_run)
271     elif args.which == 'validate':
272         call_compliance_report(device, args.validation_file)
273 
274     call_close(device)
275 
276     if args.debug:
277         call_post_connection(device)
278 
279 
280 def main():
281     args = build_help()
282     helpers.configure_logging(logger, debug=args.debug)
283     logger.debug("Starting napalm's debugging tool")
284     check_installed_packages()
285     run_tests(args)
286 
287 
288 if __name__ == '__main__':
289     main()
290
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/napalm/base/clitools/cl_napalm.py b/napalm/base/clitools/cl_napalm.py
--- a/napalm/base/clitools/cl_napalm.py
+++ b/napalm/base/clitools/cl_napalm.py
@@ -7,11 +7,11 @@
 from napalm.base.clitools import helpers
 
 # stdlib
-import pip
 import json
 import logging
 import argparse
 import getpass
+import pkg_resources
 from functools import wraps
 
 
@@ -143,9 +143,8 @@
 
 def check_installed_packages():
     logger.debug("Gathering napalm packages")
-    installed_packages = pip.get_installed_distributions()
     napalm_packages = sorted(["{}=={}".format(i.key, i.version)
-                              for i in installed_packages if i.key.startswith("napalm")])
+                              for i in pkg_resources.working_set if i.key.startswith("napalm")])
     for n in napalm_packages:
         logger.debug(n)

{"golden_diff": "diff --git a/napalm/base/clitools/cl_napalm.py b/napalm/base/clitools/cl_napalm.py\n--- a/napalm/base/clitools/cl_napalm.py\n+++ b/napalm/base/clitools/cl_napalm.py\n@@ -7,11 +7,11 @@\n from napalm.base.clitools import helpers\n \n # stdlib\n-import pip\n import json\n import logging\n import argparse\n import getpass\n+import pkg_resources\n from functools import wraps\n \n \n@@ -143,9 +143,8 @@\n \n def check_installed_packages():\n     logger.debug(\"Gathering napalm packages\")\n-    installed_packages = pip.get_installed_distributions()\n     napalm_packages = sorted([\"{}=={}\".format(i.key, i.version)\n-                              for i in installed_packages if i.key.startswith(\"napalm\")])\n+                              for i in pkg_resources.working_set if i.key.startswith(\"napalm\")])\n     for n in napalm_packages:\n         logger.debug(n)\n", "issue": "`base.clitools.cl_napalm:main` entrypoint still uses PIP internals\nhttps://github.com/napalm-automation/napalm/blob/f45fc4f8e9108cacd76ce8f5cd9182df45129480/napalm/base/clitools/cl_napalm.py#L146\r\n\r\nShould switch to `pkg_resources.find_distributions()` or similar.\n", "before_files": [{"content": "# Python3 support\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n# import helpers\nfrom napalm.base import get_network_driver\nfrom napalm.base.clitools import helpers\n\n# stdlib\nimport pip\nimport json\nimport logging\nimport argparse\nimport getpass\nfrom functools import wraps\n\n\ndef debugging(name):\n    def real_decorator(func):\n        @wraps(func)\n        def wrapper(*args, **kwargs):\n                censor_parameters = [\"password\"]\n                censored_kwargs = {k: v if k not in censor_parameters else \"*******\"\n                                   for k, v in kwargs.items()}\n                logger.debug(\"{} - Calling with args: {}, {}\".format(name, args, censored_kwargs))\n                try:\n                    r = func(*args, **kwargs)\n                    logger.debug(\"{} - Successful\".format(name))\n                    return r\n                except NotImplementedError:\n                    if name not in [\"pre_connection_tests\", \"connection_tests\",\n                                    \"post_connection_tests\"]:\n                        logger.debug(\"{} - Not implemented\".format(name))\n                except Exception as e:\n                    logger.error(\"{} - Failed: {}\".format(name, e))\n                    print(\"\\n================= Traceback =================\\n\")\n                    raise\n        return wrapper\n    return real_decorator\n\n\nlogger = logging.getLogger('napalm')\n\n\ndef build_help():\n    parser = argparse.ArgumentParser(\n        description='Command line tool to handle configuration on devices using NAPALM.'\n                    'The script will print the diff on the screen',\n        epilog='Automate all the things!!!'\n    )\n    parser.add_argument(\n        dest='hostname',\n        action='store',\n        help='Host where you want to deploy the configuration.'\n    )\n    parser.add_argument(\n        '--user', '-u',\n        dest='user',\n        action='store',\n        default=getpass.getuser(),\n        help='User for authenticating to the host. Default: user running the script.'\n    )\n    parser.add_argument(\n        '--password', '-p',\n        dest='password',\n        action='store',\n        help='Password for authenticating to the host.'\n             'If you do not provide a password in the CLI you will be prompted.',\n    )\n    parser.add_argument(\n        '--vendor', '-v',\n        dest='vendor',\n        action='store',\n        required=True,\n        help='Host Operating System.'\n    )\n    parser.add_argument(\n        '--optional_args', '-o',\n        dest='optional_args',\n        action='store',\n        help='String with comma separated key=value pairs passed via optional_args to the driver.',\n    )\n    parser.add_argument(\n        '--debug',\n        dest='debug',\n        action='store_true',\n        help='Enables debug mode; more verbosity.'\n    )\n    subparser = parser.add_subparsers(title='actions')\n\n    config = subparser.add_parser('configure', help='Perform a configuration operation')\n    config.set_defaults(which='config')\n    config.add_argument(\n        dest='config_file',\n        action='store',\n        help='File containing the configuration you want to deploy.'\n    )\n    config.add_argument(\n        '--strategy', '-s',\n        dest='strategy',\n        action='store',\n        choices=['replace', 'merge'],\n        default='replace',\n        help='Strategy to use to deploy configuration. Default: replace.'\n    )\n    config.add_argument(\n        '--dry-run', '-d',\n        dest='dry_run',\n        action='store_true',\n        default=None,\n        help='Only returns diff, it does not deploy the configuration.',\n    )\n\n    call = subparser.add_parser('call', help='Call a napalm method')\n    call.set_defaults(which='call')\n    call.add_argument(\n        dest='method',\n        action='store',\n        help='Run this method'\n    )\n    call.add_argument(\n        '--method-kwargs', '-k',\n        dest='method_kwargs',\n        action='store',\n        help='kwargs to pass to the method. For example: \"destination=1.1.1.1,protocol=bgp\"'\n    )\n\n    validate = subparser.add_parser('validate', help='Validate configuration/state')\n    validate.set_defaults(which='validate')\n    validate.add_argument(\n        dest='validation_file',\n        action='store',\n        help='Validation file containing resources derised states'\n    )\n    args = parser.parse_args()\n\n    if args.password is None:\n        password = getpass.getpass('Enter password: ')\n        setattr(args, 'password', password)\n\n    return args\n\n\ndef check_installed_packages():\n    logger.debug(\"Gathering napalm packages\")\n    installed_packages = pip.get_installed_distributions()\n    napalm_packages = sorted([\"{}=={}\".format(i.key, i.version)\n                              for i in installed_packages if i.key.startswith(\"napalm\")])\n    for n in napalm_packages:\n        logger.debug(n)\n\n\n@debugging(\"get_network_driver\")\ndef call_get_network_driver(vendor):\n    return get_network_driver(vendor)\n\n\n@debugging(\"__init__\")\ndef call_instantiating_object(driver, *args, **kwargs):\n    return driver(*args, **kwargs)\n\n\n@debugging(\"pre_connection_tests\")\ndef call_pre_connection(driver):\n    driver.pre_connection_tests()\n\n\n@debugging(\"connection_tests\")\ndef call_connection(device):\n    device.connection_tests()\n\n\n@debugging(\"post_connection_tests\")\ndef call_post_connection(device):\n    device.post_connection_tests()\n\n\n@debugging(\"get_facts\")\ndef call_facts(device):\n    facts = device.get_facts()\n    logger.debug(\"Gathered facts:\\n{}\".format(json.dumps(facts, indent=4)))\n    print(json.dumps(facts, indent=4))\n\n\n@debugging(\"close\")\ndef call_close(device):\n    return device.close()\n\n\n@debugging(\"open\")\ndef call_open_device(device):\n    return device.open()\n\n\n@debugging(\"load_replace_candidate\")\ndef call_load_replace_candidate(device, *args, **kwargs):\n    return device.load_replace_candidate(*args, **kwargs)\n\n\n@debugging(\"load_merge_candidate\")\ndef call_load_merge_candidate(device, *args, **kwargs):\n    return device.load_merge_candidate(*args, **kwargs)\n\n\n@debugging(\"compare_config\")\ndef call_compare_config(device, *args, **kwargs):\n    diff = device.compare_config(*args, **kwargs)\n    logger.debug(\"Gathered diff:\")\n    print(diff)\n    return diff\n\n\n@debugging(\"commit_config\")\ndef call_commit_config(device, *args, **kwargs):\n    return device.commit_config(*args, **kwargs)\n\n\ndef configuration_change(device, config_file, strategy, dry_run):\n    if strategy == 'replace':\n        strategy_method = call_load_replace_candidate\n    elif strategy == 'merge':\n        strategy_method = call_load_merge_candidate\n\n    strategy_method(device, filename=config_file)\n\n    diff = call_compare_config(device)\n\n    if not dry_run:\n        call_commit_config(device)\n    return diff\n\n\n@debugging(\"method\")\ndef call_getter(device, method, **kwargs):\n    logger.debug(\"{} - Attempting to resolve method\".format(method))\n    func = getattr(device, method)\n    logger.debug(\"{} - Attempting to call method with kwargs: {}\".format(method, kwargs))\n    r = func(**kwargs)\n    logger.debug(\"{} - Response\".format(method))\n    print(json.dumps(r, indent=4))\n\n\n@debugging(\"compliance_report\")\ndef call_compliance_report(device, validation_file):\n    result = device.compliance_report(validation_file)\n    print(json.dumps(result, indent=4))\n    return result\n\n\ndef run_tests(args):\n    driver = call_get_network_driver(args.vendor)\n    optional_args = helpers.parse_optional_args(args.optional_args)\n\n    device = call_instantiating_object(driver, args.hostname, args.user, password=args.password,\n                                       timeout=60, optional_args=optional_args)\n\n    if args.debug:\n        call_pre_connection(device)\n\n    call_open_device(device)\n\n    if args.debug:\n        call_connection(device)\n        call_facts(device)\n\n    if args.which == 'call':\n        method_kwargs = helpers.parse_optional_args(args.method_kwargs)\n        call_getter(device, args.method, **method_kwargs)\n    elif args.which == 'config':\n        configuration_change(device, args.config_file, args.strategy, args.dry_run)\n    elif args.which == 'validate':\n        call_compliance_report(device, args.validation_file)\n\n    call_close(device)\n\n    if args.debug:\n        call_post_connection(device)\n\n\ndef main():\n    args = build_help()\n    helpers.configure_logging(logger, debug=args.debug)\n    logger.debug(\"Starting napalm's debugging tool\")\n    check_installed_packages()\n    run_tests(args)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "napalm/base/clitools/cl_napalm.py"}], "after_files": [{"content": "# Python3 support\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n# import helpers\nfrom napalm.base import get_network_driver\nfrom napalm.base.clitools import helpers\n\n# stdlib\nimport json\nimport logging\nimport argparse\nimport getpass\nimport pkg_resources\nfrom functools import wraps\n\n\ndef debugging(name):\n    def real_decorator(func):\n        @wraps(func)\n        def wrapper(*args, **kwargs):\n                censor_parameters = [\"password\"]\n                censored_kwargs = {k: v if k not in censor_parameters else \"*******\"\n                                   for k, v in kwargs.items()}\n                logger.debug(\"{} - Calling with args: {}, {}\".format(name, args, censored_kwargs))\n                try:\n                    r = func(*args, **kwargs)\n                    logger.debug(\"{} - Successful\".format(name))\n                    return r\n                except NotImplementedError:\n                    if name not in [\"pre_connection_tests\", \"connection_tests\",\n                                    \"post_connection_tests\"]:\n                        logger.debug(\"{} - Not implemented\".format(name))\n                except Exception as e:\n                    logger.error(\"{} - Failed: {}\".format(name, e))\n                    print(\"\\n================= Traceback =================\\n\")\n                    raise\n        return wrapper\n    return real_decorator\n\n\nlogger = logging.getLogger('napalm')\n\n\ndef build_help():\n    parser = argparse.ArgumentParser(\n        description='Command line tool to handle configuration on devices using NAPALM.'\n                    'The script will print the diff on the screen',\n        epilog='Automate all the things!!!'\n    )\n    parser.add_argument(\n        dest='hostname',\n        action='store',\n        help='Host where you want to deploy the configuration.'\n    )\n    parser.add_argument(\n        '--user', '-u',\n        dest='user',\n        action='store',\n        default=getpass.getuser(),\n        help='User for authenticating to the host. Default: user running the script.'\n    )\n    parser.add_argument(\n        '--password', '-p',\n        dest='password',\n        action='store',\n        help='Password for authenticating to the host.'\n             'If you do not provide a password in the CLI you will be prompted.',\n    )\n    parser.add_argument(\n        '--vendor', '-v',\n        dest='vendor',\n        action='store',\n        required=True,\n        help='Host Operating System.'\n    )\n    parser.add_argument(\n        '--optional_args', '-o',\n        dest='optional_args',\n        action='store',\n        help='String with comma separated key=value pairs passed via optional_args to the driver.',\n    )\n    parser.add_argument(\n        '--debug',\n        dest='debug',\n        action='store_true',\n        help='Enables debug mode; more verbosity.'\n    )\n    subparser = parser.add_subparsers(title='actions')\n\n    config = subparser.add_parser('configure', help='Perform a configuration operation')\n    config.set_defaults(which='config')\n    config.add_argument(\n        dest='config_file',\n        action='store',\n        help='File containing the configuration you want to deploy.'\n    )\n    config.add_argument(\n        '--strategy', '-s',\n        dest='strategy',\n        action='store',\n        choices=['replace', 'merge'],\n        default='replace',\n        help='Strategy to use to deploy configuration. Default: replace.'\n    )\n    config.add_argument(\n        '--dry-run', '-d',\n        dest='dry_run',\n        action='store_true',\n        default=None,\n        help='Only returns diff, it does not deploy the configuration.',\n    )\n\n    call = subparser.add_parser('call', help='Call a napalm method')\n    call.set_defaults(which='call')\n    call.add_argument(\n        dest='method',\n        action='store',\n        help='Run this method'\n    )\n    call.add_argument(\n        '--method-kwargs', '-k',\n        dest='method_kwargs',\n        action='store',\n        help='kwargs to pass to the method. For example: \"destination=1.1.1.1,protocol=bgp\"'\n    )\n\n    validate = subparser.add_parser('validate', help='Validate configuration/state')\n    validate.set_defaults(which='validate')\n    validate.add_argument(\n        dest='validation_file',\n        action='store',\n        help='Validation file containing resources derised states'\n    )\n    args = parser.parse_args()\n\n    if args.password is None:\n        password = getpass.getpass('Enter password: ')\n        setattr(args, 'password', password)\n\n    return args\n\n\ndef check_installed_packages():\n    logger.debug(\"Gathering napalm packages\")\n    napalm_packages = sorted([\"{}=={}\".format(i.key, i.version)\n                              for i in pkg_resources.working_set if i.key.startswith(\"napalm\")])\n    for n in napalm_packages:\n        logger.debug(n)\n\n\n@debugging(\"get_network_driver\")\ndef call_get_network_driver(vendor):\n    return get_network_driver(vendor)\n\n\n@debugging(\"__init__\")\ndef call_instantiating_object(driver, *args, **kwargs):\n    return driver(*args, **kwargs)\n\n\n@debugging(\"pre_connection_tests\")\ndef call_pre_connection(driver):\n    driver.pre_connection_tests()\n\n\n@debugging(\"connection_tests\")\ndef call_connection(device):\n    device.connection_tests()\n\n\n@debugging(\"post_connection_tests\")\ndef call_post_connection(device):\n    device.post_connection_tests()\n\n\n@debugging(\"get_facts\")\ndef call_facts(device):\n    facts = device.get_facts()\n    logger.debug(\"Gathered facts:\\n{}\".format(json.dumps(facts, indent=4)))\n    print(json.dumps(facts, indent=4))\n\n\n@debugging(\"close\")\ndef call_close(device):\n    return device.close()\n\n\n@debugging(\"open\")\ndef call_open_device(device):\n    return device.open()\n\n\n@debugging(\"load_replace_candidate\")\ndef call_load_replace_candidate(device, *args, **kwargs):\n    return device.load_replace_candidate(*args, **kwargs)\n\n\n@debugging(\"load_merge_candidate\")\ndef call_load_merge_candidate(device, *args, **kwargs):\n    return device.load_merge_candidate(*args, **kwargs)\n\n\n@debugging(\"compare_config\")\ndef call_compare_config(device, *args, **kwargs):\n    diff = device.compare_config(*args, **kwargs)\n    logger.debug(\"Gathered diff:\")\n    print(diff)\n    return diff\n\n\n@debugging(\"commit_config\")\ndef call_commit_config(device, *args, **kwargs):\n    return device.commit_config(*args, **kwargs)\n\n\ndef configuration_change(device, config_file, strategy, dry_run):\n    if strategy == 'replace':\n        strategy_method = call_load_replace_candidate\n    elif strategy == 'merge':\n        strategy_method = call_load_merge_candidate\n\n    strategy_method(device, filename=config_file)\n\n    diff = call_compare_config(device)\n\n    if not dry_run:\n        call_commit_config(device)\n    return diff\n\n\n@debugging(\"method\")\ndef call_getter(device, method, **kwargs):\n    logger.debug(\"{} - Attempting to resolve method\".format(method))\n    func = getattr(device, method)\n    logger.debug(\"{} - Attempting to call method with kwargs: {}\".format(method, kwargs))\n    r = func(**kwargs)\n    logger.debug(\"{} - Response\".format(method))\n    print(json.dumps(r, indent=4))\n\n\n@debugging(\"compliance_report\")\ndef call_compliance_report(device, validation_file):\n    result = device.compliance_report(validation_file)\n    print(json.dumps(result, indent=4))\n    return result\n\n\ndef run_tests(args):\n    driver = call_get_network_driver(args.vendor)\n    optional_args = helpers.parse_optional_args(args.optional_args)\n\n    device = call_instantiating_object(driver, args.hostname, args.user, password=args.password,\n                                       timeout=60, optional_args=optional_args)\n\n    if args.debug:\n        call_pre_connection(device)\n\n    call_open_device(device)\n\n    if args.debug:\n        call_connection(device)\n        call_facts(device)\n\n    if args.which == 'call':\n        method_kwargs = helpers.parse_optional_args(args.method_kwargs)\n        call_getter(device, args.method, **method_kwargs)\n    elif args.which == 'config':\n        configuration_change(device, args.config_file, args.strategy, args.dry_run)\n    elif args.which == 'validate':\n        call_compliance_report(device, args.validation_file)\n\n    call_close(device)\n\n    if args.debug:\n        call_post_connection(device)\n\n\ndef main():\n    args = build_help()\n    helpers.configure_logging(logger, debug=args.debug)\n    logger.debug(\"Starting napalm's debugging tool\")\n    check_installed_packages()\n    run_tests(args)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "napalm/base/clitools/cl_napalm.py"}]}