Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pingparsing for openSUSE:Factory checked in at 2021-04-01 14:16:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pingparsing (Old) and /work/SRC/openSUSE:Factory/.python-pingparsing.new.2401 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pingparsing" Thu Apr 1 14:16:55 2021 rev:9 rq:881813 version:1.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pingparsing/python-pingparsing.changes 2021-03-06 21:19:39.357292908 +0100 +++ /work/SRC/openSUSE:Factory/.python-pingparsing.new.2401/python-pingparsing.changes 2021-04-01 14:18:10.180060171 +0200 @@ -1,0 +2,10 @@ +Sun Mar 28 11:15:28 UTC 2021 - Martin Hauke <mar...@gmx.de> + +- Update to version 1.3.0 + * Add packet size in icmp_replies + * Add received addresses in icmp_replies + * Fix incorrect parsing of domain destination with '.net' suffix + * Modify a type annotation of PingParserInterface.parse method + * Improve parsing precision of times + +------------------------------------------------------------------- Old: ---- pingparsing-1.2.0.tar.gz New: ---- pingparsing-1.3.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pingparsing.spec ++++++ --- /var/tmp/diff_new_pack.tVO4cw/_old 2021-04-01 14:18:10.980061416 +0200 +++ /var/tmp/diff_new_pack.tVO4cw/_new 2021-04-01 14:18:10.980061416 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-pingparsing -Version: 1.2.0 +Version: 1.3.0 Release: 0 Summary: CLI-tool/Python-library for parsing ping command output License: MIT ++++++ pingparsing-1.2.0.tar.gz -> pingparsing-1.3.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/.github/workflows/tests.yml new/pingparsing-1.3.0/.github/workflows/tests.yml --- old/pingparsing-1.2.0/.github/workflows/tests.yml 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/.github/workflows/tests.yml 2021-03-27 18:17:45.000000000 +0100 @@ -9,7 +9,7 @@ fail-fast: false matrix: python-version: [3.5, 3.6, 3.7, 3.8, 3.9, 3.10.0-alpha.4, pypy3] - os: [ubuntu-18.04, macos-latest, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v2 @@ -39,7 +39,7 @@ - name: Run tox run: | - tox -e cov + tox -e cov -- --discord-verbose=0 env: PYTEST_DISCORD_WEBHOOK: ${{ secrets.PYTEST_DISCORD_WEBHOOK }} @@ -49,4 +49,4 @@ coveralls --service=github env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: matrix.os == 'ubuntu-18.04' && matrix.python-version == '3.8' + if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/Makefile new/pingparsing-1.3.0/Makefile --- old/pingparsing-1.2.0/Makefile 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/Makefile 2021-03-27 18:17:45.000000000 +0100 @@ -7,7 +7,7 @@ .PHONY: check check: @-tox -e lint - pip check + python3 -m pip check .PHONY: clean clean: @@ -20,7 +20,7 @@ .PHONY: idocs idocs: - @pip install --upgrade . + @python3 -m pip install --upgrade . @make docs .PHONY: fmt @@ -39,5 +39,5 @@ .PHONY: setup setup: - @pip install --upgrade -e .[test] releasecmd tox - pip check + @python3 -m pip install --upgrade -e .[test] releasecmd tox + python3 -m pip check diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/README.rst new/pingparsing-1.3.0/README.rst --- old/pingparsing-1.2.0/README.rst 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/README.rst 2021-03-27 18:17:45.000000000 +0100 @@ -103,29 +103,35 @@ "packet_receive": 3, "packet_loss_count": 0, "packet_loss_rate": 0.0, - "rtt_min": 19.885, - "rtt_avg": 38.829, - "rtt_max": 57.751, - "rtt_mdev": 15.459, + "rtt_min": 36.997, + "rtt_avg": 49.1, + "rtt_max": 60.288, + "rtt_mdev": 9.533, "packet_duplicate_count": 0, "packet_duplicate_rate": 0.0, "icmp_replies": [ { + "destination": "nrt20s21-in-f14.1e100.net (172.217.175.110)", + "bytes": 64, "icmp_seq": 1, - "ttl": 53, - "time": 19.8, + "ttl": 113, + "time": 50.0, "duplicate": false }, { + "destination": "nrt20s21-in-f14.1e100.net (172.217.175.110)", + "bytes": 64, "icmp_seq": 2, - "ttl": 53, - "time": 38.8, + "ttl": 113, + "time": 60.2, "duplicate": false }, { + "destination": "nrt20s21-in-f14.1e100.net (172.217.175.110)", + "bytes": 64, "icmp_seq": 3, - "ttl": 53, - "time": 57.7, + "ttl": 113, + "time": 36.9, "duplicate": false } ] @@ -422,7 +428,7 @@ :Output: :: - [extract ping statistics] + [ping statistics] { "destination": "google.com", "packet_transmit": 5, @@ -437,12 +443,12 @@ "packet_duplicate_rate": 0.0 } - [extract icmp replies] - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37), 'icmp_seq': 1, 'ttl': 39, 'time': 148.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37), 'icmp_seq': 2, 'ttl': 39, 'time': 137.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 38), 'icmp_seq': 3, 'ttl': 39, 'time': 137.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 39), 'icmp_seq': 4, 'ttl': 39, 'time': 136.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 40), 'icmp_seq': 5, 'ttl': 39, 'time': 136.0, 'duplicate': False} + [icmp replies] + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37, 3555), 'icmp_seq': 1, 'ttl': 39, 'time': 148.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37, 787175), 'icmp_seq': 2, 'ttl': 39, 'time': 137.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 38, 787642), 'icmp_seq': 3, 'ttl': 39, 'time': 137.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 39, 787653), 'icmp_seq': 4, 'ttl': 39, 'time': 136.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 40, 788365), 'icmp_seq': 5, 'ttl': 39, 'time': 136.0, 'duplicate': False} Recommended ping command execution @@ -511,6 +517,8 @@ +--------------+-----------------------------------+ | Ubuntu 18.04 | ``iputils-ping 20161105-1ubuntu2``| +--------------+-----------------------------------+ +| Ubuntu 20.04 | ``iputils-ping 20190709-3`` | ++--------------+-----------------------------------+ | Debian 8.6 | ``iputils-ping 20121221-5+b2`` | +--------------+-----------------------------------+ | Fedora 25 | ``iputils-20161105-1.fc25.x86_64``| diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/docs/pages/introduction/supported_environment.txt new/pingparsing-1.3.0/docs/pages/introduction/supported_environment.txt --- old/pingparsing-1.2.0/docs/pages/introduction/supported_environment.txt 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/docs/pages/introduction/supported_environment.txt 2021-03-27 18:17:45.000000000 +0100 @@ -14,6 +14,8 @@ +--------------+-----------------------------------+ | Ubuntu 18.04 | ``iputils-ping 20161105-1ubuntu2``| +--------------+-----------------------------------+ +| Ubuntu 20.04 | ``iputils-ping 20190709-3`` | ++--------------+-----------------------------------+ | Debian 8.6 | ``iputils-ping 20121221-5+b2`` | +--------------+-----------------------------------+ | Fedora 25 | ``iputils-20161105-1.fc25.x86_64``| diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/docs/pages/usage/cli_usage.txt new/pingparsing-1.3.0/docs/pages/usage/cli_usage.txt --- old/pingparsing-1.2.0/docs/pages/usage/cli_usage.txt 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/docs/pages/usage/cli_usage.txt 2021-03-27 18:17:45.000000000 +0100 @@ -78,29 +78,35 @@ "packet_receive": 3, "packet_loss_count": 0, "packet_loss_rate": 0.0, - "rtt_min": 19.885, - "rtt_avg": 38.829, - "rtt_max": 57.751, - "rtt_mdev": 15.459, + "rtt_min": 36.997, + "rtt_avg": 49.1, + "rtt_max": 60.288, + "rtt_mdev": 9.533, "packet_duplicate_count": 0, "packet_duplicate_rate": 0.0, "icmp_replies": [ { + "destination": "nrt20s21-in-f14.1e100.net (172.217.175.110)", + "bytes": 64, "icmp_seq": 1, - "ttl": 53, - "time": 19.8, + "ttl": 113, + "time": 50.0, "duplicate": false }, { + "destination": "nrt20s21-in-f14.1e100.net (172.217.175.110)", + "bytes": 64, "icmp_seq": 2, - "ttl": 53, - "time": 38.8, + "ttl": 113, + "time": 60.2, "duplicate": false }, { + "destination": "nrt20s21-in-f14.1e100.net (172.217.175.110)", + "bytes": 64, "icmp_seq": 3, - "ttl": 53, - "time": 57.7, + "ttl": 113, + "time": 36.9, "duplicate": false } ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/docs/pages/usage/library.rst new/pingparsing-1.3.0/docs/pages/usage/library.rst --- old/pingparsing-1.2.0/docs/pages/usage/library.rst 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/docs/pages/usage/library.rst 2021-03-27 18:17:45.000000000 +0100 @@ -71,7 +71,7 @@ :Output: :: - [extract ping statistics] + [ping statistics] { "destination": "google.com", "packet_transmit": 5, @@ -86,12 +86,12 @@ "packet_duplicate_rate": 0.0 } - [extract icmp replies] - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37), 'icmp_seq': 1, 'ttl': 39, 'time': 148.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37), 'icmp_seq': 2, 'ttl': 39, 'time': 137.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 38), 'icmp_seq': 3, 'ttl': 39, 'time': 137.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 39), 'icmp_seq': 4, 'ttl': 39, 'time': 136.0, 'duplicate': False} - {'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 40), 'icmp_seq': 5, 'ttl': 39, 'time': 136.0, 'duplicate': False} + [icmp replies] + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37, 3555), 'icmp_seq': 1, 'ttl': 39, 'time': 148.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 37, 787175), 'icmp_seq': 2, 'ttl': 39, 'time': 137.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 38, 787642), 'icmp_seq': 3, 'ttl': 39, 'time': 137.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 39, 787653), 'icmp_seq': 4, 'ttl': 39, 'time': 136.0, 'duplicate': False} + {'destination': '74.125.24.100', 'bytes': 64, 'timestamp': datetime.datetime(2018, 4, 29, 0, 55, 40, 788365), 'icmp_seq': 5, 'ttl': 39, 'time': 136.0, 'duplicate': False} Recommended ping command execution diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/examples/parse_sample.py new/pingparsing-1.3.0/examples/parse_sample.py --- old/pingparsing-1.2.0/examples/parse_sample.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/examples/parse_sample.py 2021-03-27 18:17:45.000000000 +0100 @@ -16,24 +16,24 @@ stats = parser.parse( dedent( """\ - PING google.com (74.125.24.100) 56(84) bytes of data. - [1524930937.003555] 64 bytes from 74.125.24.100: icmp_seq=1 ttl=39 time=148 ms - [1524930937.787175] 64 bytes from 74.125.24.100: icmp_seq=2 ttl=39 time=137 ms - [1524930938.787642] 64 bytes from 74.125.24.100: icmp_seq=3 ttl=39 time=137 ms - [1524930939.787653] 64 bytes from 74.125.24.100: icmp_seq=4 ttl=39 time=136 ms - [1524930940.788365] 64 bytes from 74.125.24.100: icmp_seq=5 ttl=39 time=136 ms + PING google.com (74.125.24.100) 56(84) bytes of data. + [1524930937.003555] 64 bytes from 74.125.24.100: icmp_seq=1 ttl=39 time=148 ms + [1524930937.787175] 64 bytes from 74.125.24.100: icmp_seq=2 ttl=39 time=137 ms + [1524930938.787642] 64 bytes from 74.125.24.100: icmp_seq=3 ttl=39 time=137 ms + [1524930939.787653] 64 bytes from 74.125.24.100: icmp_seq=4 ttl=39 time=136 ms + [1524930940.788365] 64 bytes from 74.125.24.100: icmp_seq=5 ttl=39 time=136 ms - --- google.com ping statistics --- - 5 packets transmitted, 5 received, 0% packet loss, time 4001ms - rtt min/avg/max/mdev = 136.537/139.174/148.006/4.425 ms - """ + --- google.com ping statistics --- + 5 packets transmitted, 5 received, 0% packet loss, time 4001ms + rtt min/avg/max/mdev = 136.537/139.174/148.006/4.425 ms + """ ) ) print("[ping statistics]") print(json.dumps(stats.as_dict(), indent=4)) - print("\n[icmp reply]") + print("\n[icmp replies]") for icmp_reply in stats.icmp_replies: print(icmp_reply) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/pingparsing/__version__.py new/pingparsing-1.3.0/pingparsing/__version__.py --- old/pingparsing-1.2.0/pingparsing/__version__.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/pingparsing/__version__.py 2021-03-27 18:17:45.000000000 +0100 @@ -1,6 +1,6 @@ __author__ = "Tsuyoshi Hombashi" __copyright__ = "Copyright 2016, {}".format(__author__) __license__ = "MIT License" -__version__ = "1.2.0" +__version__ = "1.3.0" __maintainer__ = __author__ __email__ = "tsuyoshi.homba...@gmail.com" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/pingparsing/_interface.py new/pingparsing-1.3.0/pingparsing/_interface.py --- old/pingparsing-1.2.0/pingparsing/_interface.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/pingparsing/_interface.py 2021-03-27 18:17:45.000000000 +0100 @@ -1,10 +1,10 @@ import abc -from typing import List +from typing import Sequence from ._stats import PingStats class PingParserInterface(metaclass=abc.ABCMeta): @abc.abstractmethod - def parse(self, ping_message: List[str]) -> PingStats: # pragma: no cover + def parse(self, ping_message: Sequence[str]) -> PingStats: # pragma: no cover pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/pingparsing/_parser.py new/pingparsing-1.3.0/pingparsing/_parser.py --- old/pingparsing-1.2.0/pingparsing/_parser.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/pingparsing/_parser.py 2021-03-27 18:17:45.000000000 +0100 @@ -20,6 +20,8 @@ class IcmpReplyKey: + DESTINATION = "destination" + BYTES = "bytes" TIMESTAMP = "timestamp" TIMESTAMP_NO_ANS = "timestamp_no_ans" SEQUENCE_NO = "icmp_seq" @@ -30,10 +32,14 @@ class PingParser(PingParserInterface): + _BYTES_PATTERN = r"\s*(?P<{key}>[0-9]+) bytes".format(key=IcmpReplyKey.BYTES) + _DEST_PATTERN = r"(?P<{key}>[a-zA-Z0-9:\-\.\(\)% ]+)".format( + key=IcmpReplyKey.DESTINATION + ) # host or ipv4/ipv6 addr _IPADDR_PATTERN = r"(\d{1,3}\.){3}\d{1,3}" - _ICMP_SEQ_PATTERN = r"icmp_seq=(?P<icmp_seq>\d+)" - _TTL_PATTERN = r"ttl=(?P<ttl>\d+)" - _TIME_PATTERN = r"time=(?P<time>[0-9\.]+)" + _ICMP_SEQ_PATTERN = r"\s*icmp_seq=(?P<{key}>\d+)".format(key=IcmpReplyKey.SEQUENCE_NO) + _TTL_PATTERN = r"\s*ttl=(?P<{key}>\d+)".format(key=IcmpReplyKey.TTL) + _TIME_PATTERN = r"\s*time[=<](?P<{key}>[0-9\.]+)".format(key=IcmpReplyKey.TIME) def __init__(self, timezone: Optional[tzinfo] = None) -> None: self.__timezone = timezone @@ -76,7 +82,13 @@ continue results = match.groupdict() - reply = {} # type: Dict[str, Union[bool, float, int, datetime]] + reply = {} # type: Dict[str, Union[str, bool, float, int, datetime]] + + if IcmpReplyKey.DESTINATION in results: + reply[IcmpReplyKey.DESTINATION] = results[IcmpReplyKey.DESTINATION] + + if IcmpReplyKey.BYTES in results: + reply[IcmpReplyKey.BYTES] = int(results[IcmpReplyKey.BYTES]) if results.get(IcmpReplyKey.TIMESTAMP): reply[IcmpReplyKey.TIMESTAMP] = self.__timestamp_to_datetime( @@ -87,13 +99,13 @@ results[IcmpReplyKey.TIMESTAMP_NO_ANS] ) - if results.get(IcmpReplyKey.SEQUENCE_NO): + if IcmpReplyKey.SEQUENCE_NO in results: reply[IcmpReplyKey.SEQUENCE_NO] = int(results[IcmpReplyKey.SEQUENCE_NO]) - if results.get(IcmpReplyKey.TTL): + if IcmpReplyKey.TTL in results: reply[IcmpReplyKey.TTL] = int(results[IcmpReplyKey.TTL]) - if results.get(IcmpReplyKey.TIME): + if IcmpReplyKey.TIME in results: reply[IcmpReplyKey.TIME] = float(results[IcmpReplyKey.TIME]) if duplicate_packet_regexp.search(line): @@ -119,7 +131,11 @@ return (lines[stats_headline_idx], packet_info_line, body_line_list) def _parse_destination(self, stats_headline: str) -> str: - return stats_headline.lstrip("--- ").rstrip(" ping statistics ---") + match = re.search(self._stats_headline_pattern, stats_headline) + if not match: + return "unknown" + + return match.groupdict()[IcmpReplyKey.DESTINATION].strip(":") def __find_stats_headline_idx(self, lines: Sequence[str], re_stats_header: Pattern) -> int: for i, line in enumerate(lines): @@ -172,7 +188,7 @@ def _is_support_packet_duplicate(self) -> bool: # pragma: no cover return False - def parse(self, ping_message: List[str]) -> PingStats: # pragma: no cover + def parse(self, ping_message: Sequence[str]) -> PingStats: # pragma: no cover return PingStats() def _preprocess_parse_stats( @@ -186,8 +202,8 @@ def _parser_name(self) -> str: return "Linux" - _TIMESTAMP_PATTERN = r"(?P<timestamp>\[[0-9\.]+\])" - _NO_ANS_TIMESTAMP_PATTERN = r"(?P<timestamp_no_ans>\[[0-9\.]+\])" + _TIMESTAMP_PATTERN = r"(?P<{key}>\[[0-9\.]+\])".format(key=IcmpReplyKey.TIMESTAMP) + _NO_ANS_TIMESTAMP_PATTERN = r"(?P<{key}>\[[0-9\.]+\])".format(key=IcmpReplyKey.TIMESTAMP_NO_ANS) @property def _icmp_no_ans_pattern(self) -> str: @@ -197,23 +213,25 @@ def _icmp_reply_pattern(self) -> str: return ( self._TIMESTAMP_PATTERN - + r"?\s?.+ from .+?: " + + "?" + + self._BYTES_PATTERN + + r"\s+from " + + self._DEST_PATTERN + + ":" + self._ICMP_SEQ_PATTERN - + " " + self._TTL_PATTERN - + " " + self._TIME_PATTERN ) @property def _stats_headline_pattern(self) -> str: - return "--- .* ping statistics ---" + return r"--- {} ping statistics ---".format(self._DEST_PATTERN) @property def _is_support_packet_duplicate(self) -> bool: return True - def parse(self, ping_message: List[str]) -> PingStats: + def parse(self, ping_message: Sequence[str]) -> PingStats: icmp_replies = self._parse_icmp_reply(ping_message) stats_headline, packet_info_line, body_line_list = self._preprocess_parse_stats( lines=ping_message @@ -280,17 +298,24 @@ @property def _icmp_reply_pattern(self) -> str: - return " from .+?: " + self._TTL_PATTERN + " " + self._TIME_PATTERN + return ( + " from " + + self._DEST_PATTERN + + r":\s*bytes=(?P<{key}>[0-9]+)".format(key=IcmpReplyKey.BYTES) + + self._TIME_PATTERN + + "ms" + + self._TTL_PATTERN + ) @property def _stats_headline_pattern(self) -> str: - return "^Ping statistics for " + return r"^Ping statistics for {}".format(self._DEST_PATTERN) @property def _is_support_packet_duplicate(self) -> bool: return False - def parse(self, ping_message: List[str]) -> PingStats: + def parse(self, ping_message: Sequence[str]) -> PingStats: icmp_replies = self._parse_icmp_reply(ping_message) stats_headline, packet_info_line, body_line_list = self._preprocess_parse_stats( lines=ping_message @@ -345,9 +370,6 @@ icmp_replies=icmp_replies, ) - def _parse_destination(self, stats_headline): - return stats_headline.lstrip("Ping statistics for ").rstrip(":") - class MacOsPingParser(PingParser): @property @@ -357,23 +379,24 @@ @property def _icmp_reply_pattern(self) -> str: return ( - " from .+?: " + self._BYTES_PATTERN + + r"\s+from " + + self._DEST_PATTERN + + ":" + self._ICMP_SEQ_PATTERN - + " " + self._TTL_PATTERN - + " " + self._TIME_PATTERN ) @property def _stats_headline_pattern(self) -> str: - return "--- .* ping statistics ---" + return r"--- {} ping statistics ---".format(self._DEST_PATTERN) @property def _is_support_packet_duplicate(self) -> bool: return True - def parse(self, ping_message: List[str]) -> PingStats: + def parse(self, ping_message: Sequence[str]) -> PingStats: icmp_replies = self._parse_icmp_reply(ping_message) stats_headline, packet_info_line, body_line_list = self._preprocess_parse_stats( lines=ping_message @@ -441,14 +464,20 @@ @property def _icmp_reply_pattern(self) -> str: return ( - " from .+?: " + r"seq=(?P<icmp_seq>\d+) " + self._TTL_PATTERN + " " + self._TIME_PATTERN + self._BYTES_PATTERN + + r"\s+from " + + self._DEST_PATTERN + + ": " + + r"seq=(?P<{key}>\d+) ".format(key=IcmpReplyKey.SEQUENCE_NO) + + self._TTL_PATTERN + + self._TIME_PATTERN ) @property def _is_support_packet_duplicate(self) -> bool: return True - def parse(self, ping_message: List[str]) -> PingStats: + def parse(self, ping_message: Sequence[str]) -> PingStats: icmp_replies = self._parse_icmp_reply(ping_message) stats_headline, packet_info_line, body_line_list = self._preprocess_parse_stats( lines=ping_message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/pingparsing/_stats.py new/pingparsing-1.3.0/pingparsing/_stats.py --- old/pingparsing-1.2.0/pingparsing/_stats.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/pingparsing/_stats.py 2021-03-27 18:17:45.000000000 +0100 @@ -155,6 +155,9 @@ """ ICMP packet reply information. + .. note: + ``time<1ms`` considered as ``time=1`` + Returns: |list| of |dict|: """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/pingparsing/_typing.py new/pingparsing-1.3.0/pingparsing/_typing.py --- old/pingparsing-1.2.0/pingparsing/_typing.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/pingparsing/_typing.py 2021-03-27 18:17:45.000000000 +0100 @@ -5,4 +5,4 @@ TimeArg = Union[hr.Time, int, str, None] -IcmpReplies = Sequence[Dict[str, Union[bool, float, int, datetime]]] +IcmpReplies = Sequence[Dict[str, Union[str, bool, float, int, datetime]]] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/pyproject.toml new/pingparsing-1.3.0/pyproject.toml --- old/pingparsing-1.2.0/pyproject.toml 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/pyproject.toml 2021-03-27 18:17:45.000000000 +0100 @@ -1,3 +1,6 @@ +[build-system] +requires = ["setuptools", "wheel"] + [tool.black] line-length = 100 exclude = ''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/requirements/test_requirements.txt new/pingparsing-1.3.0/requirements/test_requirements.txt --- old/pingparsing-1.2.0/requirements/test_requirements.txt 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/requirements/test_requirements.txt 2021-03-27 18:17:45.000000000 +0100 @@ -1,3 +1,3 @@ pytest>=6.0.1 -pytest-discord>=0.0.5;python_version<="3.9" +pytest-discord>=0.0.6 pytest-md-report>=0.0.12 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/setup.py new/pingparsing-1.3.0/setup.py --- old/pingparsing-1.2.0/setup.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/setup.py 2021-03-27 18:17:45.000000000 +0100 @@ -40,7 +40,6 @@ with open(os.path.join(REQUIREMENT_DIR, "test_requirements.txt")) as f: tests_requires = [line.strip() for line in f if line.strip()] -setuptools_require = ["setuptools>=38.3.0"] CLI_OPT_REQUIRES = ["loguru>=0.4.1,<1", "Pygments>=2.1<3"] setuptools.setup( @@ -63,7 +62,7 @@ "Tracker": "{:s}/issues".format(REPOSITORY_URL), }, python_requires=">=3.5", - install_requires=setuptools_require + install_requires, + install_requires=install_requires, extras_require={"test": tests_requires, "cli": CLI_OPT_REQUIRES}, classifiers=[ "Development Status :: 5 - Production/Stable", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/test/data.py new/pingparsing-1.3.0/test/data.py --- old/pingparsing-1.2.0/test/data.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/test/data.py 2021-03-27 18:17:45.000000000 +0100 @@ -68,11 +68,46 @@ "rtt_mdev": 1.430, }, [ - {"icmp_seq": 1, "ttl": 53, "time": 68.5, "duplicate": False}, - {"icmp_seq": 2, "ttl": 53, "time": 67.7, "duplicate": False}, - {"icmp_seq": 3, "ttl": 53, "time": 65.6, "duplicate": False}, - {"icmp_seq": 4, "ttl": 53, "time": 65.6, "duplicate": False}, - {"icmp_seq": 5, "ttl": 53, "time": 64.9, "duplicate": False}, + { + "destination": "104.244.42.65", + "bytes": 64, + "icmp_seq": 1, + "ttl": 53, + "time": 68.5, + "duplicate": False, + }, + { + "destination": "104.244.42.65", + "bytes": 64, + "icmp_seq": 2, + "ttl": 53, + "time": 67.7, + "duplicate": False, + }, + { + "destination": "104.244.42.65", + "bytes": 64, + "icmp_seq": 3, + "ttl": 53, + "time": 65.6, + "duplicate": False, + }, + { + "destination": "104.244.42.65", + "bytes": 64, + "icmp_seq": 4, + "ttl": 53, + "time": 65.6, + "duplicate": False, + }, + { + "destination": "104.244.42.65", + "bytes": 64, + "icmp_seq": 5, + "ttl": 53, + "time": 64.9, + "duplicate": False, + }, ], ) @@ -107,6 +142,8 @@ }, [ { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": datetime(2018, 4, 28, 15, 55, 37, 3555, tzinfo=pytz.UTC), "icmp_seq": 1, "ttl": 39, @@ -114,6 +151,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": datetime(2018, 4, 28, 15, 55, 37, 787175, tzinfo=pytz.UTC), "icmp_seq": 2, "ttl": 39, @@ -121,6 +160,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": datetime(2018, 4, 28, 15, 55, 38, 787642, tzinfo=pytz.UTC), "icmp_seq": 3, "ttl": 39, @@ -128,6 +169,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": datetime(2018, 4, 28, 15, 55, 39, 787653, tzinfo=pytz.UTC), "icmp_seq": 4, "ttl": 39, @@ -135,6 +178,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": datetime(2018, 4, 28, 15, 55, 40, 788365, tzinfo=pytz.UTC), "icmp_seq": 5, "ttl": 39, @@ -172,9 +217,30 @@ "rtt_mdev": 7.098, }, [ - {"icmp_seq": 1, "ttl": 50, "time": 64.3, "duplicate": False}, - {"icmp_seq": 2, "ttl": 50, "time": 49.7, "duplicate": False}, - {"icmp_seq": 3, "ttl": 50, "time": 48.8, "duplicate": False}, + { + "destination": "kix05s01-in-f14.1e100.net (172.217.26.110)", + "bytes": 64, + "icmp_seq": 1, + "ttl": 50, + "time": 64.3, + "duplicate": False, + }, + { + "destination": "kix05s01-in-f14.1e100.net (172.217.26.110)", + "bytes": 64, + "icmp_seq": 2, + "ttl": 50, + "time": 49.7, + "duplicate": False, + }, + { + "destination": "kix05s01-in-f14.1e100.net (172.217.26.110)", + "bytes": 64, + "icmp_seq": 3, + "ttl": 50, + "time": 48.8, + "duplicate": False, + }, ], ) @@ -213,5 +279,28 @@ "rtt_max": 194, "rtt_mdev": None, }, - [], + [ + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 87.0, "duplicate": False}, + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 97.0, "duplicate": False}, + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 56.0, "duplicate": False}, + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 95.0, "duplicate": False}, + { + "bytes": 32, + "destination": "216.58.196.238", + "ttl": 51, + "time": 194.0, + "duplicate": False, + }, + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 98.0, "duplicate": False}, + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 93.0, "duplicate": False}, + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 96.0, "duplicate": False}, + {"bytes": 32, "destination": "216.58.196.238", "ttl": 51, "time": 96.0, "duplicate": False}, + { + "bytes": 32, + "destination": "216.58.196.238", + "ttl": 51, + "time": 165.0, + "duplicate": False, + }, + ], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/test/test_cli.py new/pingparsing-1.3.0/test/test_cli.py --- old/pingparsing-1.2.0/test/test_cli.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/test/test_cli.py 2021-03-27 18:17:45.000000000 +0100 @@ -97,6 +97,8 @@ "packet_duplicate_rate": 0.0, "icmp_replies": [ { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": "2018-04-28T15:55:37.003555+00:00", "icmp_seq": 1, "ttl": 39, @@ -104,6 +106,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": "2018-04-28T15:55:37.787175+00:00", "icmp_seq": 2, "ttl": 39, @@ -111,6 +115,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": "2018-04-28T15:55:38.787642+00:00", "icmp_seq": 3, "ttl": 39, @@ -118,6 +124,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": "2018-04-28T15:55:39.787653+00:00", "icmp_seq": 4, "ttl": 39, @@ -125,6 +133,8 @@ "duplicate": False, }, { + "destination": "74.125.24.100", + "bytes": 64, "timestamp": "2018-04-28T15:55:40.788365+00:00", "icmp_seq": 5, "ttl": 39, @@ -137,7 +147,7 @@ @pytest.mark.xfail(run=False) class Test_cli_pipe: - def test_normal(self, tmpdir): + def test_normal(self): runner = SubprocessRunner([sys.executable, "-m", "pingparsing"]) runner.run(input=DEBIAN_SUCCESS_0.value) @@ -146,7 +156,7 @@ assert runner.returncode == 0 assert json.loads(runner.stdout) == DEBIAN_SUCCESS_0.expected - def test_normal_w_option(self, tmpdir): + def test_normal_w_option(self): expected = dedent( """\ { @@ -163,18 +173,24 @@ "packet_duplicate_rate": 0.0, "icmp_replies": [ { + "destination": "kix05s01-in-f14.1e100.net (172.217.26.110)", + "bytes": 64, "icmp_seq": 1, "ttl": 50, "time": 64.3, "duplicate": false }, { + "destination": "kix05s01-in-f14.1e100.net (172.217.26.110)", + "bytes": 64, "icmp_seq": 2, "ttl": 50, "time": 49.7, "duplicate": false }, { + "destination": "kix05s01-in-f14.1e100.net (172.217.26.110)", + "bytes": 64, "icmp_seq": 3, "ttl": 50, "time": 48.8, @@ -214,6 +230,7 @@ count = 1 dest_list = ["google.com", "twitter.com"] runner = SubprocessRunner([sys.executable, "-m", "pingparsing"] + dest_list + ["-c", count]) + print(runner.command_str, file=sys.stderr) runner.run() print_result(stdout=runner.stdout, stderr=runner.stderr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/test/test_pingparsing.py new/pingparsing-1.3.0/test/test_pingparsing.py --- old/pingparsing-1.2.0/test/test_pingparsing.py 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/test/test_pingparsing.py 2021-03-27 18:17:45.000000000 +0100 @@ -104,6 +104,8 @@ "duplicate": False, }, { + "bytes": 64, + "destination": "192.168.11.222", "timestamp": datetime(2020, 8, 8, 10, 5, 33, 81898, tzinfo=pytz.UTC), "icmp_seq": 2, "ttl": 64, @@ -126,6 +128,8 @@ "duplicate": False, }, { + "bytes": 64, + "destination": "192.168.11.222", "timestamp": datetime(2020, 8, 8, 10, 5, 37, 180326, tzinfo=pytz.UTC), "icmp_seq": 6, "ttl": 64, @@ -133,6 +137,8 @@ "duplicate": False, }, { + "bytes": 64, + "destination": "192.168.11.222", "timestamp": datetime(2020, 8, 8, 10, 5, 38, 201538, tzinfo=pytz.UTC), "icmp_seq": 7, "ttl": 64, @@ -226,11 +232,46 @@ "rtt_mdev": 8.292, }, [ - {"icmp_seq": 0, "ttl": 53, "time": 20.482, "duplicate": False}, - {"icmp_seq": 1, "ttl": 53, "time": 32.55, "duplicate": False}, - {"icmp_seq": 2, "ttl": 53, "time": 32.013, "duplicate": False}, - {"icmp_seq": 3, "ttl": 53, "time": 28.498, "duplicate": False}, - {"icmp_seq": 4, "ttl": 53, "time": 46.093, "duplicate": False}, + { + "bytes": 64, + "destination": "172.217.6.238", + "icmp_seq": 0, + "ttl": 53, + "time": 20.482, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "172.217.6.238", + "icmp_seq": 1, + "ttl": 53, + "time": 32.55, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "172.217.6.238", + "icmp_seq": 2, + "ttl": 53, + "time": 32.013, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "172.217.6.238", + "icmp_seq": 3, + "ttl": 53, + "time": 28.498, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "172.217.6.238", + "icmp_seq": 4, + "ttl": 53, + "time": 46.093, + "duplicate": False, + }, ], ) MACOS_SUCCESS_1 = PingTestData( @@ -306,6 +347,30 @@ }, [], ) +MACOS_UNREACHABLE_2 = PingTestData( + dedent( + """\ + PING example.net (93.184.216.34): 56 data bytes + + --- example.net ping statistics --- + 10 packets transmitted, 0 packets received, 100.0% packet loss + """ + ), + { + "destination": "example.net", + "packet_transmit": 10, + "packet_receive": 0, + "packet_loss_count": 10, + "packet_loss_rate": 100.0, + "packet_duplicate_count": 0, + "packet_duplicate_rate": None, + "rtt_min": None, + "rtt_avg": None, + "rtt_max": None, + "rtt_mdev": None, + }, + [], +) MACOS_DUPLICATE_0 = PingTestData( dedent( """\ @@ -393,17 +458,130 @@ "rtt_mdev": None, }, [ - {"icmp_seq": 0, "ttl": 64, "time": 0.936, "duplicate": False}, - {"icmp_seq": 0, "ttl": 64, "time": 1.003, "duplicate": True}, - {"icmp_seq": 1, "ttl": 64, "time": 0.802, "duplicate": False}, - {"icmp_seq": 2, "ttl": 64, "time": 0.696, "duplicate": False}, - {"icmp_seq": 3, "ttl": 64, "time": 0.664, "duplicate": False}, - {"icmp_seq": 4, "ttl": 64, "time": 1.194, "duplicate": False}, - {"icmp_seq": 5, "ttl": 64, "time": 0.613, "duplicate": False}, - {"icmp_seq": 6, "ttl": 64, "time": 0.898, "duplicate": False}, - {"icmp_seq": 8, "ttl": 64, "time": 1.066, "duplicate": False}, - {"icmp_seq": 9, "ttl": 64, "time": 1.144, "duplicate": False}, - {"icmp_seq": 9, "ttl": 64, "time": 1.219, "duplicate": True}, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 0, + "ttl": 64, + "time": 0.936, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 0, + "ttl": 64, + "time": 1.003, + "duplicate": True, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 1, + "ttl": 64, + "time": 0.802, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 2, + "ttl": 64, + "time": 0.696, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 3, + "ttl": 64, + "time": 0.664, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 4, + "ttl": 64, + "time": 1.194, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 5, + "ttl": 64, + "time": 0.613, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 6, + "ttl": 64, + "time": 0.898, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 8, + "ttl": 64, + "time": 1.066, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 9, + "ttl": 64, + "time": 1.144, + "duplicate": False, + }, + { + "bytes": 64, + "destination": "192.168.2.106", + "icmp_seq": 9, + "ttl": 64, + "time": 1.219, + "duplicate": True, + }, + ], +) + +IPV6_LINUX = PingTestData( + dedent( + r"""\ + PING ff02::2%usb0(ff02::2%usb0) 56 data bytes + 64 bytes from fe80::783c:caff:fe12:b46c%usb0: icmp_seq=1 ttl=64 time=2.71 ms + + --- ff02::2%usb0 ping statistics --- + 1 packets transmitted, 1 received, 0% packet loss, time 0ms + rtt min/avg/max/mdev = 2.708/2.708/2.708/0.000 ms + """ + ), + { + "destination": r"ff02::2%usb0", + "packet_transmit": 1, + "packet_receive": 1, + "packet_duplicate_count": 0, + "packet_duplicate_rate": 0, + "packet_loss_count": 0, + "packet_loss_rate": 0.0, + "rtt_min": 2.708, + "rtt_avg": 2.708, + "rtt_max": 2.708, + "rtt_mdev": 0.0, + }, + [ + { + "bytes": 64, + "destination": r"fe80::783c:caff:fe12:b46c%usb0", + "icmp_seq": 1, + "ttl": 64, + "time": 2.71, + "duplicate": False, + }, ], ) @@ -441,7 +619,17 @@ "rtt_max": 33.0, "rtt_mdev": None, }, - [], + [ + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 16.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 6.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 12.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 16.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 8.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 33.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 13.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 23.0, "duplicate": False}, + {"bytes": 32, "destination": "192.168.2.106", "ttl": 64, "time": 1.0, "duplicate": False}, + ], ) WINDOWS_UNREACHABLE_0 = PingTestData( dedent( @@ -495,6 +683,7 @@ [MACOS_SUCCESS_1, "macOS"], [MACOS_UNREACHABLE_0, "macOS"], [MACOS_UNREACHABLE_1, "macOS"], + [MACOS_UNREACHABLE_2, "macOS"], [MACOS_DUPLICATE_0, "macOS"], [ALPINE_LINUX_SUCCESS, "AlpineLinux"], [ALPINE_LINUX_DUP_LOSS, "AlpineLinux"], @@ -503,6 +692,7 @@ [WINDOWS_UNREACHABLE_0, "Windows"], [WINDOWS_UNREACHABLE_1, "Windows"], [WINDOWS_UNREACHABLE_2, "Windows"], + [IPV6_LINUX, "Linux"], ], ) def test_normal_text(self, ping_parser, test_data, parser_name): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.2.0/tox.ini new/pingparsing-1.3.0/tox.ini --- old/pingparsing-1.2.0/tox.ini 2021-01-31 17:04:33.000000000 +0100 +++ new/pingparsing-1.3.0/tox.ini 2021-03-27 18:17:45.000000000 +0100 @@ -57,7 +57,7 @@ commands = autoflake --in-place --recursive --remove-all-unused-imports --ignore-init-module-imports . isort . - black invoke_pytest.py setup.py test pingparsing + black invoke_pytest.py setup.py test pingparsing examples [testenv:lint] basepython = python3.8 @@ -77,6 +77,7 @@ [testenv:readme] changedir = docs deps = + .[cli] path readmemaker>=1.0.0 commands =