Skip to content

Commit

Permalink
0.10.0 (2023-11-03)
Browse files Browse the repository at this point in the history
------------------
* [new] SwVersion()
  • Loading branch information
vladimirs-git committed Nov 3, 2023
1 parent 2292b76 commit ad1db1b
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
CHANGELOG
=========

0.10.0 (2023-11-03)
------------------
* [new] SwVersion()


0.9.0 (2023-10-23)
------------------
* [new] intf_map.py ALL_SHORT
Expand Down
35 changes: 30 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ netports
Python tools for managing ranges of VLANs, TCP/UDP ports, IP protocols, Interfaces
Recommended for scripting in telecommunications networks.

.. contents:: **Contents**
:local:


Requirements
------------
Expand All @@ -34,15 +31,18 @@ or install the package from github.com release

.. code:: bash
pip install https://github.com/vladimirs-git/netports/archive/refs/tags/0.9.0.tar.gz
pip install https://github.com/vladimirs-git/netports/archive/refs/tags/0.10.0.tar.gz
or install the package from github.com repository

.. code:: bash
pip install git+https://github.com/vladimirs-git/netports@0.9.0
pip install git+https://github.com/vladimirs-git/netports@0.10.0
.. contents:: **Contents**
:local:


TCP/UDP ports
-------------
Expand Down Expand Up @@ -572,6 +572,31 @@ Return
`./examples/intfs.py`_


SwVersion()
...........
**SwVersion(text)**
Parse the given version string and return *SwVersion* object who can
compare (>, >=, <, <=) software versions of network devices: Cisco, FortiGate, HP, etc.


.. code:: python
import re
from netports import SwVersion
text = "Cisco IOS Software, C2960X Software (C2960X-UNIVERSALK9-M), Version 15.2(4)E10, ..."
text = re.search(r"Version (\S+),", text)[1]
version1 = SwVersion(text) # 15.2(4)E10
version2 = SwVersion("15.2(4)E11")
assert version1 < version2
assert version1 <= version2
assert not version1 > version2
assert not version1 >= version2
print(version1) # 15.2(4)e10
print(version2) # 15.2(4)e11
.. _`./examples/tcp_udp.py` : ./examples/tcp_udp.py
.. _`./examples/vlan.py` : ./examples/vlan.py
Expand Down
1 change: 1 addition & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
from netports.item import Item
from netports.ports import inumbers, parse_range, snumbers
from netports.range import Range
from netports.swversion import SwVersion
from netports.tcp import stcp, itcp
from netports.vlan import ivlan, svlan
2 changes: 2 additions & 0 deletions netports/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from netports.item import Item
from netports.ports import inumbers, parse_range, snumbers
from netports.range import Range
from netports.swversion import SwVersion
from netports.tcp import stcp, itcp
from netports.vlan import ivlan, svlan

Expand All @@ -19,6 +20,7 @@
"Item",
"NetportsValueError",
"Range",
"SwVersion",
"iip",
"intfrange",
"inumbers",
Expand Down
28 changes: 27 additions & 1 deletion netports/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Any, Iterable

from netports.static import BRIEF_ALL_I, BRIEF_ALL_S, SPLITTER
from netports.types_ import LAny, LStr, StrInt, IStrInt, LInt, T2Str, T3Str
from netports.types_ import LAny, LStr, StrInt, IStrInt, LInt, T2Str, T3Str, T4Str


# =============================== str ================================
Expand Down Expand Up @@ -60,6 +60,32 @@ def findall3(pattern: str, string: str, flags=0) -> T3Str:
return "", "", ""


def findall4(pattern: str, string: str, flags=0) -> T4Str:
"""Parses 4 items of re.findall(). If nothing is found, returns 4 empty strings
::
:param pattern: Regex pattern, where 4 groups with parentheses in pattern are required
:param string: String where need to find pattern
:param flags: findall flags
:return: Three interested substrings
:example:
pattern = "a(b)(c)(d)(e)f"
string = "abcdef"
return: "b", "c", "d", "e"
"""
result = (re.findall(pattern=pattern, string=string, flags=flags) or [("", "", "", "")])[0]
if isinstance(result, tuple) and len(result) >= 4:
return result[0], result[1], result[2], result[3]
return "", "", "", ""


def repr_params(*args, **kwargs) -> str:
"""Makes params for __repr__() method"""
args_ = ", ".join([f"{v!r}" for v in args if v])
kwargs_ = ", ".join([f"{k}={v!r}" for k, v in kwargs.items() if v])
params = [s for s in (args_, kwargs_) if s]
return ", ".join(params)


def join(items: LAny) -> str:
"""Joins items by "," """
return SPLITTER.join([str(i) for i in items])
Expand Down
86 changes: 86 additions & 0 deletions netports/swversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""Software Version"""
from typing import Tuple

from packaging.version import Version

from netports import helpers as h


class SwVersion(Version):
"""SwVersion"""

def __init__(self, text: str):
"""SwVersion
:param text: Cisco version text: "12.2(55)SE12"
:type text: str
"""
self._text = self._init_name(name=text)
version, nano = self._parse_version(self._text)
super().__init__(version)
self._nano: int = nano

# ========================== redefined ===========================

def __repr__(self) -> str:
name = self.__class__.__name__
params = h.repr_params(self._text)
return f"{name}({params})"

def __str__(self) -> str:
return self._text

def __hash__(self) -> int:
return hash(str(self))

def __eq__(self, other: object) -> bool:
if not isinstance(other, SwVersion):
return False
return self._text == other._text

def __ne__(self, other: object) -> bool:
return not self.__eq__(other)

# =========================== property ===========================

@property
def public(self) -> str:
"""Public version text"""
return self._text

@property
def nano(self) -> int:
"""4th part of version
:example:
version = SwVersion("12.2(55)SE14")
version.nano -> 14
"""
return self._nano

# =========================== helpers ============================

@staticmethod
def _init_name(**kwargs) -> str:
"""Init name"""
name = kwargs.get("name")
if name is None:
name = ""
return str(name).lower()

@staticmethod
def _parse_version(text: str) -> Tuple[str, int]:
"""Init SwVersion. Split `text` to *Version* and `nano` (4th digit)"""
nano = 0
items = list(h.findall4(r"(\d+)\D+(\d+)\D+(\d+)\D+(\d+)", text))
if items[3]:
nano = int(items[3])
else:
items = list(h.findall3(r"(\d+)\D+(\d+)\D+(\d+)", text))
if not items[0]:
items = list(h.findall2(r"(\d+)\D+(\d+)", text))
if not items[0]:
if version := h.findall1(r"(\d+)", text):
items = [version]
else:
items = []
version = ".".join(items)
return version, nano
1 change: 1 addition & 0 deletions netports/types_.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
StrInt = Union[str, int]
T2Str = Tuple[str, str]
T3Str = Tuple[str, str, str]
T4Str = Tuple[str, str, str, str]
T5Str = Tuple[str, str, str, str, str]
TIntStr = Tuple[int, str]

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "netports"
version = "0.9.0"
version = "0.10.0"
authors = [{ name="Vladimir Prusakov", email="[email protected]" }]
description = "Python tools for managing ranges of VLANs, TCP/UDP ports, IP protocols, Interfaces"
readme = "README.rst"
Expand All @@ -21,7 +21,7 @@ classifiers = [
"Homepage" = "https://github.com/vladimirs-git/netports"
"Repository" = "https://github.com/vladimirs-git/netports"
"Bug Tracker" = "https://github.com/vladimirs-git/netports/issues"
"Download URL" = "https://github.com/vladimirs-git/netports/archive/refs/tags/0.9.0.tar.gz"
"Download URL" = "https://github.com/vladimirs-git/netports/archive/refs/tags/0.10.0.tar.gz"
[tool.setuptools.packages.find]
include = ["netports"]
[tool.setuptools.package-data]
Expand Down
27 changes: 27 additions & 0 deletions tests/test__helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

from netports import helpers as h

APOSTROPHE = "'"
SPEECH = "\""


class Test(unittest.TestCase):
"""unittest helpers.py"""
Expand Down Expand Up @@ -64,6 +67,30 @@ def test_valid__findall3(self):
actual = h.findall3(pattern=pattern, string=string)
self.assertEqual(expected, actual, msg=f"{pattern=}")

def test_valid__findall4(self):
"""findall4()"""
for pattern, string, req in [
("", "abcdef", ("", "", "", "")),
("typo", "abcdef", ("", "", "", "")),
("(b)", "abcdef", ("", "", "", "")),
("(b)(c)(d)(e)", "abcdef", ("b", "c", "d", "e")),
("(b)(c)(d)(e)(f)", "abcdef", ("b", "c", "d", "e")),
]:
result = h.findall4(pattern=pattern, string=string)
self.assertEqual(result, req, msg=f"{pattern=}")

def test_valid__repr_params(self):
"""init.repr_params()"""
for args, kwargs, req in [
([], {}, ""),
(["a"], {}, "\"a\""),
([], dict(a="a"), "a=\"a\""),
(["a", "b"], dict(c="c", d="d"), "\"a\", \"b\", c=\"c\", d=\"d\""),
]:
result = h.repr_params(*args, **kwargs)
result = result.replace(APOSTROPHE, SPEECH)
self.assertEqual(result, req, msg=f"{kwargs=}")

# =============================== bool ===============================

def test_valid__is_all(self):
Expand Down
Loading

0 comments on commit ad1db1b

Please sign in to comment.