Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
30714a1
Bump sphinx from 7.2.6 to 7.3.7
dependabot[bot] Apr 19, 2024
e9d5966
Fix issue #2086 stripping whitespace (#2087)
Smertan May 16, 2024
935b83d
Closes #2028: Fix typo
May 19, 2024
6ae9be3
Bump pytest from 7.3.1 to 8.2.1
dependabot[bot] May 20, 2024
fc72b67
Bump types-setuptools from 69.2.0.20240317 to 69.5.0.20240519
dependabot[bot] May 20, 2024
eed8110
Merge pull request #2090 from napalm-automation/dependabot/pip/types-…
mirceaulinic May 21, 2024
fcaf0b9
Merge pull request #2089 from napalm-automation/dependabot/pip/pytest…
mirceaulinic May 21, 2024
5e93cd9
Merge branch 'develop' into fix_typo
mirceaulinic May 21, 2024
e06ac59
Merge pull request #2072 from napalm-automation/dependabot/pip/sphinx…
mirceaulinic May 21, 2024
9b21db7
Bump mypy from 1.9.0 to 1.10.0
dependabot[bot] May 21, 2024
0e13abd
Bump black from 24.3.0 to 24.4.2
dependabot[bot] May 21, 2024
1d51236
Merge pull request #2079 from napalm-automation/dependabot/pip/black-…
mirceaulinic May 21, 2024
25b7684
Merge pull request #2076 from napalm-automation/dependabot/pip/mypy-1…
mirceaulinic May 21, 2024
c898c02
Merge branch 'develop' into fix_typo
mirceaulinic May 21, 2024
bc71ca0
Merge pull request #2088 from vishnubraj/fix_typo
mirceaulinic May 21, 2024
c7eb04a
Bump jinja2 from 3.1.3 to 3.1.4 (#2082)
dependabot[bot] May 21, 2024
937dab0
Bump types-six from 1.16.21.20240311 to 1.16.21.20240513 (#2083)
dependabot[bot] May 21, 2024
7c291b3
Bump coveralls from 3.3.1 to 4.0.1 (#2085)
dependabot[bot] May 21, 2024
d332a70
Bump ansible from 9.4.0 to 9.6.0
dependabot[bot] May 23, 2024
6afc4b7
Bump types-requests from 2.31.0.20240406 to 2.32.0.20240521
dependabot[bot] May 23, 2024
f0efc0b
Bump types-setuptools from 69.5.0.20240519 to 69.5.0.20240522
dependabot[bot] May 23, 2024
4517225
correct typo in typing object
bewing Jul 15, 2024
e31e5e3
rework napalm.eos.EOSDriver to use JSON
bewing Jul 15, 2024
5bb8d0e
ignore typing on TypedDict defaultdict
bewing Jul 16, 2024
b7a2c13
add no peers test for eos.get_bgp_neighbors
bewing Jul 16, 2024
c649a94
add no bgp test for eos.get_bgp_neighbors
bewing Jul 16, 2024
f3b2077
generate new test case for issue #1759
bewing Jul 16, 2024
981c5ca
check for correct uptime in eos bgp neighbors
bewing Jul 26, 2024
72ba65e
Merge pull request #2116 from napalm-automation/eos-bgp-json
bewing Jul 26, 2024
e725559
added pyenv venv file to the gitignore (#2145)
hellt Aug 21, 2024
6e5d7d1
Fix UnboundLocalError: cannot access local variable 'seconds' where i…
Sep 20, 2024
19706c3
Fix unexpected speed unit in show interfaces parsing
Sep 20, 2024
3d65683
Add tests on NXOSSSHDriver.parse_uptime method
Oct 14, 2024
d0d2a3e
Merge pull request #2148 from n-rodriguez/wip/fixes
bewing Oct 15, 2024
17e0aeb
Improve nxos_ssh version handling (#2152)
bewing Nov 5, 2024
e6c5da2
Bump ansible version in docs requirements (#2158)
bewing Jan 3, 2025
9a539a8
Draft: Update eos CLI vrf command (#2157)
bewing Jan 3, 2025
99192df
Support non-total model testing in helper
bewing Jan 22, 2025
145c7b7
Update NTP data return definition
bewing Jan 22, 2025
c02a749
Add support for NTP server details to EOS
bewing Jan 22, 2025
053e899
Add kwarg for model subset testing
bewing Jan 23, 2025
95b0aba
Refactor nxos ntp for mypy typing
bewing Jan 23, 2025
8e9f538
remove unused EOS NTP peer textfsm
bewing Jan 23, 2025
eef08bc
use plain dict in IOSDriver.get_bgp_neighbors_detail() (#2163)
paketb0te Feb 9, 2025
2518279
Merge branch 'develop' into ntp_details
ktbyers Feb 9, 2025
6cacce8
Merge pull request #2160 from napalm-automation/ntp_details
bewing Feb 10, 2025
d21c466
Bump urllib3 from 2.2.1 to 2.2.2 (#2102)
dependabot[bot] Feb 20, 2025
4890994
Bump types-requests from 2.32.0.20240521 to 2.32.0.20240712 (#2114)
dependabot[bot] Feb 20, 2025
8cc41bc
Bump pytest from 8.2.1 to 8.3.2 (#2132)
dependabot[bot] Feb 20, 2025
710398b
Bump mypy from 1.10.0 to 1.11.1 (#2136)
dependabot[bot] Feb 20, 2025
ff8307a
Bump types-pyyaml from 6.0.12.20240311 to 6.0.12.20240808 (#2140)
dependabot[bot] Feb 20, 2025
24454b2
Bump types-requests from 2.32.0.20240712 to 2.32.0.20241016 (#2168)
dependabot[bot] Feb 24, 2025
2d6f825
Bump pytest from 8.3.2 to 8.3.4 (#2169)
dependabot[bot] Feb 24, 2025
e7dfb93
Bump urllib3 from 2.2.2 to 2.3.0 (#2171)
dependabot[bot] Feb 24, 2025
e388c19
Bump ansible from 9.6.1 to 11.2.0 (#2174)
dependabot[bot] Feb 26, 2025
f3f59c9
Bump markupsafe from 2.1.5 to 3.0.2 (#2180)
dependabot[bot] Feb 26, 2025
5bc2bfc
Bump ansible from 11.2.0 to 11.3.0 (#2185)
dependabot[bot] Feb 27, 2025
0d365a7
Bump ttp-templates from 0.3.6 to 0.3.7 (#2181)
dependabot[bot] Mar 1, 2025
9b0e385
Bump jinja2 from 3.1.4 to 3.1.5 (#2184)
dependabot[bot] Mar 1, 2025
d153758
Bump types-pyyaml from 6.0.12.20240808 to 6.0.12.20241230 (#2182)
dependabot[bot] Mar 1, 2025
bce9899
Bump types-six from 1.16.21.20240513 to 1.17.0.20241205 (#2187)
dependabot[bot] Mar 2, 2025
5e9872f
Bump pytest from 8.3.4 to 8.3.5 (#2190)
dependabot[bot] Mar 3, 2025
1ebd868
Bump mock from 5.1.0 to 5.2.0 (#2191)
dependabot[bot] Mar 3, 2025
67b1c0c
[EOS] Fix confirm_commit for ssh transport and text encoding
carljungg Mar 5, 2025
9c6aa2c
Discard unexpected NTP strings (#2198)
bewing Mar 21, 2025
b89dcc5
Remove external mock dependency (#2155)
s-t-e-v-e-n-k Mar 21, 2025
636344a
Bump jinja2 from 3.1.5 to 3.1.6 (#2196)
dependabot[bot] Mar 21, 2025
7e50986
Add support for PY3.13; use vendored version of telnetlib (#2137)
ktbyers Mar 24, 2025
9b1b3aa
Bump pytest-cov from 5.0.0 to 6.0.0 (#2173)
dependabot[bot] Mar 24, 2025
e18f96f
Bump mypy from 1.11.1 to 1.15.0 (#2172)
dependabot[bot] Mar 24, 2025
75eb5cf
Bump sphinx from 7.3.7 to 8.2.3 (#2189)
dependabot[bot] Mar 24, 2025
e644fb8
Bump types-six from 1.17.0.20241205 to 1.17.0.20250304 (#2193)
dependabot[bot] Mar 24, 2025
ff59653
Bump types-requests from 2.32.0.20241016 to 2.32.0.20250306 (#2195)
dependabot[bot] Mar 24, 2025
7220567
fix banner when transport is ssh
derekdainys Jul 30, 2024
a24d360
add ssh tests + blank line heredoc test
derekdainys Mar 10, 2025
c0bdcad
remove whitespace and comment
derekdainys Mar 10, 2025
e3ea774
black format
derekdainys Mar 10, 2025
091b1c4
remove datetime and re
derekdainys Mar 10, 2025
ba5dfd8
noqa for linter
derekdainys Mar 10, 2025
96d1981
reformat heredoc
derekdainys Mar 10, 2025
92d8f37
fix mock
derekdainys Apr 18, 2025
df7bb9a
Rename ssh_config_file to ssh_config for iosxr_netconf driver (#2218)
ubaumann Apr 29, 2025
92f73c4
Merge branch 'develop' into eos-ssh-banners
ktbyers Apr 30, 2025
2624a61
Merge pull request #2135 from derekdainys/eos-ssh-banners
bewing May 1, 2025
77921f6
Explicitly close IOSXR connection (#2214)
justinbrink May 8, 2025
f36447d
Use importlib for version
bewing Jul 9, 2025
d9adff9
Use pkgutil to check installed modules
bewing Jul 9, 2025
43ec70a
Remove legacy subpackage versions
bewing Jul 9, 2025
7407aa1
Merge pull request #2241 from napalm-automation/iss2240
bewing Jul 15, 2025
8bdd887
pytest wrapper should return None, not result
bewing Jul 16, 2024
13b5ffe
remove invalid pytest flags
bewing Jul 16, 2024
2b6e26a
Merge pull request #2120 from napalm-automation/iss2118
bewing Jul 15, 2025
abccc4d
Remove transitive dependency scp from requirements.txt (#2243)
karyotakisg Jul 17, 2025
5659743
Fix pyez dependency issue (#2247)
ktbyers Aug 5, 2025
4946eba
Dependabot updates
ktbyers Aug 5, 2025
77f2dd8
More dependabot updates
ktbyers Aug 5, 2025
1247328
Prep for napalm 5.1.0 release
ktbyers Aug 5, 2025
3523f85
Add Brandon as an author
ktbyers Aug 5, 2025
3587c9f
Fix author emails
ktbyers Aug 5, 2025
3675ed3
Fix linting issue
ktbyers Aug 5, 2025
db485ea
Roll two dependabot dev deps
ktbyers Aug 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: [3.8, 3.9, 3.10.9, 3.11, 3.12.0]
python-version: ["3.9", "3.10.9", "3.11", "3.12", "3.13"]

steps:
- name: Checkout repository
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ docs/_static/
.venv
.vscode
.devcontainer
.python-version

env
*.swp
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ Install
pip install napalm
```

*Note*: Beginning with release 5.1.0 and later, NAPALM offers support for
Python 3.9+ only.

*Note*: Beginning with release 5.0.0 and later, NAPALM offers support for
Python 3.8+ only.

*Note*: Beginning with release 4.0.0 and later, NAPALM offers support for
Python 3.7+ only.

*Note*: Beginning with release 3.0.0 and later, NAPALM offers support for
Python 3.6+ only.


Upgrading
=========
Expand Down
12 changes: 6 additions & 6 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
urllib3==2.2.1 # https://github.com/readthedocs/readthedocs.org/issues/10290
sphinx==7.2.6
urllib3==2.3.0 # https://github.com/readthedocs/readthedocs.org/issues/10290
sphinx==7.4.7
sphinx-rtd-theme==2.0.0
invoke==2.2.0
jinja2==3.1.3
MarkupSafe==2.1.5
pytest==7.3.1
ansible==9.4.0
jinja2==3.1.6
MarkupSafe==3.0.2
pytest==8.3.5
ansible==11.3.0
12 changes: 6 additions & 6 deletions napalm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import pkg_resources
from importlib.metadata import version, PackageNotFoundError
import sys
import logging

Expand All @@ -17,14 +17,14 @@

# Verify Python Version that is running
try:
if not (sys.version_info.major == 3 and sys.version_info.minor >= 7):
raise RuntimeError("NAPALM requires Python 3.7 or greater")
if not (sys.version_info.major == 3 and sys.version_info.minor >= 9):
raise RuntimeError("NAPALM requires Python 3.9 or greater")
except AttributeError:
raise RuntimeError("NAPALM requires Python 3.7 or greater")
raise RuntimeError("NAPALM requires Python 3.9 or greater")

try:
__version__ = pkg_resources.get_distribution("napalm").version
except pkg_resources.DistributionNotFound:
__version__ = version("napalm")
except PackageNotFoundError:
__version__ = "Not installed"

__all__ = ("get_network_driver", "SUPPORTED_DRIVERS")
Expand Down
17 changes: 14 additions & 3 deletions napalm/base/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ def get_lldp_neighbors_detail(

def get_bgp_config(
self, group: str = "", neighbor: str = ""
) -> models.BPGConfigGroupDict:
) -> models.BGPConfigGroupDict:
"""
Returns a dictionary containing the BGP configuration.
Can return either the whole config, either the config only for a group or neighbor.
Expand Down Expand Up @@ -921,12 +921,23 @@ def get_ntp_servers(self) -> Dict[str, models.NTPServerDict]:
"""
Returns the NTP servers configuration as dictionary.
The keys of the dictionary represent the IP Addresses of the servers.
Inner dictionaries do not have yet any available keys.
Inner dictionaries MAY contain information regarding per-server configuration.

Example::

{
'192.168.0.1': {},
'192.168.0.1':
{
'address': '192.168.0.1',
'port': 123,
'version': 4,
'association_type': 'SERVER',
'iburst': False,
'prefer': False,
'network_instance': 'default',
'source_address': '192.0.2.1',
'key_id': -1,
},
'17.72.148.53': {},
'37.187.56.220': {},
'162.158.20.18': {}
Expand Down
9 changes: 5 additions & 4 deletions napalm/base/clitools/cl_napalm.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import logging
import argparse
import getpass
import pkg_resources
import pkgutil
from importlib.metadata import version
from functools import wraps


Expand Down Expand Up @@ -156,9 +157,9 @@ def check_installed_packages():
logger.debug("Gathering napalm packages")
napalm_packages = sorted(
[
"{}=={}".format(i.key, i.version)
for i in pkg_resources.working_set
if i.key.startswith("napalm")
"{}=={}".format(i.name, version(i.name))
for i in list(pkgutil.iter_modules())
if i.name.startswith("napalm")
]
)
for n in napalm_packages:
Expand Down
24 changes: 15 additions & 9 deletions napalm/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@
"AFDict", {"sent_prefixes": int, "accepted_prefixes": int, "received_prefixes": int}
)

BPGConfigGroupDict = TypedDict(
"BPGConfigGroupDict",
BGPConfigGroupDict = TypedDict(
"BGPConfigGroupDict",
{
"type": str,
"description": str,
Expand Down Expand Up @@ -188,8 +188,8 @@
},
)

BGPStateAdressFamilyDict = TypedDict(
"BGPStateAdressFamilyDict",
BGPStateAddressFamilyDict = TypedDict(
"BGPStateAddressFamilyDict",
{"received_prefixes": int, "accepted_prefixes": int, "sent_prefixes": int},
)

Expand All @@ -203,7 +203,7 @@
"is_enabled": bool,
"description": str,
"uptime": int,
"address_family": Dict[str, BGPStateAdressFamilyDict],
"address_family": Dict[str, BGPStateAddressFamilyDict],
},
)

Expand All @@ -223,16 +223,22 @@

NTPPeerDict = TypedDict(
"NTPPeerDict",
{
# will populate it in the future wit potential keys
},
{},
total=False,
)

NTPServerDict = TypedDict(
"NTPServerDict",
{
# will populate it in the future wit potential keys
"address": str,
"port": int,
"version": int,
"association_type": str,
"iburst": bool,
"prefer": bool,
"network_instance": str,
"source_address": str,
"key_id": int,
},
total=False,
)
Expand Down
2 changes: 1 addition & 1 deletion napalm/base/test/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def test_get_bgp_config(self):
result = len(get_bgp_config) > 0

for bgp_group in get_bgp_config.values():
result = result and self._test_model(models.BPGConfigGroupDict, bgp_group)
result = result and self._test_model(models.BGPConfigGroupDict, bgp_group)
for bgp_neighbor in bgp_group.get("neighbors", {}).values():
result = result and self._test_model(
models.BGPConfigNeighborDict, bgp_neighbor
Expand Down
12 changes: 8 additions & 4 deletions napalm/base/test/getters.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def mock_wrapper(cls, test_case):
attr.current_test = "" # Empty them to avoid side effects
attr.current_test_case = "" # Empty them to avoid side effects

return result
return None

@functools.wraps(func)
def real_wrapper(cls, test_case):
Expand Down Expand Up @@ -249,7 +249,7 @@ def test_get_bgp_config(self, test_case):
assert get_bgp_config == {} or len(get_bgp_config) > 0

for bgp_group in get_bgp_config.values():
assert helpers.test_model(models.BPGConfigGroupDict, bgp_group)
assert helpers.test_model(models.BGPConfigGroupDict, bgp_group)
for bgp_neighbor in bgp_group.get("neighbors", {}).values():
assert helpers.test_model(models.BGPConfigNeighborDict, bgp_neighbor)

Expand Down Expand Up @@ -311,7 +311,9 @@ def test_get_ntp_peers(self, test_case):

for peer, peer_details in get_ntp_peers.items():
assert isinstance(peer, str)
assert helpers.test_model(models.NTPPeerDict, peer_details)
assert helpers.test_model(
models.NTPPeerDict, peer_details, allow_subset=True
)

return get_ntp_peers

Expand All @@ -323,7 +325,9 @@ def test_get_ntp_servers(self, test_case):

for server, server_details in get_ntp_servers.items():
assert isinstance(server, str)
assert helpers.test_model(models.NTPServerDict, server_details)
assert helpers.test_model(
models.NTPServerDict, server_details, allow_subset=True
)

return get_ntp_servers

Expand Down
19 changes: 12 additions & 7 deletions napalm/base/test/helpers.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
"""Several methods to help with the tests."""


def test_model(model, data):
def test_model(model, data, allow_subset=False):
"""Return if the dictionary `data` complies with the `model`."""
# Access the underlying schema for a TypedDict directly
model = model.__annotations__
same_keys = set(model.keys()) == set(data.keys())
annotations = model.__annotations__
if allow_subset:
same_keys = set(data.keys()) <= set(annotations.keys())
source = data
else:
same_keys = set(annotations.keys()) == set(data.keys())
source = annotations

if not same_keys:
print(
"model_keys: {}\ndata_keys: {}".format(
sorted(model.keys()), sorted(data.keys())
sorted(annotations.keys()), sorted(data.keys())
)
)

correct_class = True
for key, instance_class in model.items():
correct_class = isinstance(data[key], instance_class) and correct_class
for key in source.keys():
correct_class = isinstance(data[key], annotations[key]) and correct_class
if not correct_class:
print(
"key: {}\nmodel_class: {}\ndata_class: {}".format(
key, instance_class, data[key].__class__
key, annotations[key], data[key].__class__
)
)

Expand Down
Loading