Hello community, here is the log from the commit of package python-pingparsing for openSUSE:Factory checked in at 2020-04-08 19:55:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pingparsing (Old) and /work/SRC/openSUSE:Factory/.python-pingparsing.new.3248 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pingparsing" Wed Apr 8 19:55:13 2020 rev:4 rq:791536 version:1.0.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pingparsing/python-pingparsing.changes 2020-03-17 13:09:09.873753781 +0100 +++ /work/SRC/openSUSE:Factory/.python-pingparsing.new.3248/python-pingparsing.changes 2020-04-08 19:55:16.925061960 +0200 @@ -1,0 +2,7 @@ +Sat Apr 4 10:30:25 UTC 2020 - Martin Hauke <mar...@gmx.de> + +- Update to version 1.0.2 + * Make it possible execute the CLI with python -m pingparsing + * Update requirements + +------------------------------------------------------------------- Old: ---- pingparsing-1.0.1.tar.gz New: ---- pingparsing-1.0.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pingparsing.spec ++++++ --- /var/tmp/diff_new_pack.B5Eae2/_old 2020-04-08 19:55:17.741062556 +0200 +++ /var/tmp/diff_new_pack.B5Eae2/_new 2020-04-08 19:55:17.745062559 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-pingparsing -Version: 1.0.1 +Version: 1.0.2 Release: 0 Summary: CLI-tool/Python-library for parsing ping command output License: MIT @@ -29,24 +29,23 @@ BuildRequires: %{python_module setuptools >= 38.3.0} BuildRequires: fdupes BuildRequires: python-rpm-macros -Requires: python-humanreadable >= 0.0.7 -Requires: python-loguru >= 0.4.1 -Requires: python-pyparsing >= 2.0.3 -Requires: python-setuptools >= 38.3.0 -Requires: python-six >= 1.10.0 -Requires: python-subprocrunner >= 0.17.0 -Requires: python-typepy >= 0.6.3 -BuildArch: noarch # SECTION test requirements BuildRequires: %{python_module Logbook >= 0.12.3} -BuildRequires: %{python_module humanreadable >= 0.0.7} +BuildRequires: %{python_module humanreadable >= 0.1.0} BuildRequires: %{python_module pyparsing >= 2.0.3} BuildRequires: %{python_module pytest} BuildRequires: %{python_module simplejson} -BuildRequires: %{python_module six >= 1.10.0} -BuildRequires: %{python_module subprocrunner >= 0.17.0} -BuildRequires: %{python_module typepy >= 0.6.3} +BuildRequires: %{python_module subprocrunner >= 1.2.1} +BuildRequires: %{python_module typepy >= 1.0.0} # /SECTION +Requires: python-humanreadable >= 0.1.0 +Requires: python-loguru >= 0.4.1 +Requires: python-pyparsing >= 2.0.3 +Requires: python-setuptools >= 38.3.0 +Requires: python-simplejson +Requires: python-subprocrunner >= 1.2.1 +Requires: python-typepy >= 1.0.0 +BuildArch: noarch %python_subpackages %description @@ -54,7 +53,7 @@ %prep %setup -q -n pingparsing-%{version} -sed -i -e '/^#!\//, 1d' pingparsing/cli.py +sed -i -e '/^#!\//, 1d' pingparsing/__main__.py %build %python_build ++++++ pingparsing-1.0.1.tar.gz -> pingparsing-1.0.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/MANIFEST.in new/pingparsing-1.0.2/MANIFEST.in --- old/pingparsing-1.0.1/MANIFEST.in 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/MANIFEST.in 2020-04-04 12:15:05.000000000 +0200 @@ -3,6 +3,7 @@ include README.rst include setup.cfg include tox.ini +include */py.typed recursive-include test * recursive-include requirements * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/Makefile new/pingparsing-1.0.2/Makefile --- old/pingparsing-1.0.1/Makefile 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/Makefile 2020-04-04 12:15:05.000000000 +0200 @@ -8,6 +8,7 @@ check: @-tox -e lint travis lint + pip check .PHONY: clean clean: @@ -40,3 +41,4 @@ .PHONY: setup setup: @pip install --upgrade -e .[test] tox + pip check diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/README.rst new/pingparsing-1.0.2/README.rst --- old/pingparsing-1.0.1/README.rst 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/README.rst 2020-04-04 12:15:05.000000000 +0200 @@ -4,7 +4,7 @@ Summary ========= -`pingparsing <https://github.com/thombashi/pingparsing>`__ is a CLI-tool/Python-library for parsing ping command output. +`pingparsing <https://github.com/thombashi/pingparsing>`__ is a CLI-tool/Python-library parser and transmitter for ping command. .. image:: https://badge.fury.io/py/pingparsing.svg :target: https://badge.fury.io/py/pingparsing @@ -32,11 +32,12 @@ CLI Usage ==================== -A CLI command included in the ``pingparsing`` packaged. The ``pingparsing`` command could do the following: +A CLI tool (``pingparsing`` command) included in the packaged. The command could do the following: -- Execute ping and parse the result -- Parse ping result file(s) -- Parse from the standard input +- Execute ``ping`` and parse the result +- Parse ping results from: + - file(s) + - the standard input Execute ping and parse the result -------------------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/docs/pages/introduction/summary.txt new/pingparsing-1.0.2/docs/pages/introduction/summary.txt --- old/pingparsing-1.0.1/docs/pages/introduction/summary.txt 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/docs/pages/introduction/summary.txt 2020-04-04 12:15:05.000000000 +0200 @@ -1 +1 @@ -pingparsing is a CLI-tool/Python-library for parsing ping command output. +pingparsing is a CLI-tool/Python-library parser and transmitter for ping command. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/docs/pages/usage/cli_usage.txt new/pingparsing-1.0.2/docs/pages/usage/cli_usage.txt --- old/pingparsing-1.0.1/docs/pages/usage/cli_usage.txt 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/docs/pages/usage/cli_usage.txt 2020-04-04 12:15:05.000000000 +0200 @@ -1,10 +1,11 @@ CLI Usage ==================== -A CLI command included in the ``pingparsing`` packaged. The ``pingparsing`` command could do the following: +A CLI tool (``pingparsing`` command) included in the packaged. The command could do the following: -- Execute ping and parse the result -- Parse ping result file(s) -- Parse from the standard input +- Execute ``ping`` and parse the result +- Parse ping results from: + - file(s) + - the standard input Execute ping and parse the result -------------------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/docs/update_command_help.py new/pingparsing-1.0.2/docs/update_command_help.py --- old/pingparsing-1.0.1/docs/update_command_help.py 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/docs/update_command_help.py 2020-04-04 12:15:05.000000000 +0200 @@ -1,13 +1,14 @@ #!/usr/bin/env python3 import os +import sys from textwrap import indent from subprocrunner import SubprocessRunner def main(): - proc = SubprocessRunner(["pingparsing", "-h"]) + proc = SubprocessRunner([sys.executable, "-m", "pingparsing", "-h"]) proc.run(env=dict(os.environ, LC_ALL="C.UTF-8")) help_file_path = "pages/usage/cli_help.txt" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/pingparsing/__main__.py new/pingparsing-1.0.2/pingparsing/__main__.py --- old/pingparsing-1.0.1/pingparsing/__main__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pingparsing-1.0.2/pingparsing/__main__.py 2020-04-04 12:15:05.000000000 +0200 @@ -0,0 +1,391 @@ +#!/usr/bin/env python3 + +""" +.. codeauthor:: Tsuyoshi Hombashi <tsuyoshi.homba...@gmail.com> +""" + +import argparse +import multiprocessing +import os +import sys +from datetime import datetime +from textwrap import dedent +from typing import Any, Dict, Optional, Tuple + +import humanreadable as hr +from subprocrunner import CommandError + +from pingparsing._logger import logger, set_logger + +from .__version__ import __version__ +from ._pingparsing import PingParsing +from ._pingtransmitter import PingTransmitter +from ._typing import TimeArg + + +try: + import simplejson as json +except ImportError: + import json # type: ignore + + +DEFAULT_COUNT = 10 +QUIET_LOG_LEVEL = "QUIET" +TIMESTAMP_TYPES = (int, float, str) + + +class TimestampFormat: + NONE = "none" + EPOCH = "epoch" + DATETIME = "datetime" + LIST = (NONE, EPOCH, DATETIME) + + +class LogLevel: + DEBUG = "DEBUG" + INFO = "INFO" + + +def _get_unit_help_msg() -> str: + return ", ".join(["/".join(values) for values in hr.Time.get_text_units().values()]) + + +def parse_option() -> argparse.Namespace: + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=dedent( + """\ + Documentation: https://pingparsing.rtfd.io/ + Issue tracker: https://github.com/thombashi/pingparsing/issues + """ + ), + ) + parser.add_argument( + "-V", "--version", action="version", version="%(prog)s {}".format(__version__) + ) + + use_stdin, found_stdin_specifier = is_use_stdin() + if not use_stdin or found_stdin_specifier: + parser.add_argument( + "destination_or_file", + nargs="+", + help="Destinations to send ping, or files to parse. '-' for parse the standard input.", + ) + + parser.add_argument( + "--max-workers", + type=int, + help="""Number of threads for when multiple destination/file + specified. defaults to equals to two times number of cores. + """, + ) + + group = parser.add_argument_group("Ping Options") # type: ignore + group.add_argument( + "--timestamp", + choices=TimestampFormat.LIST, + default=TimestampFormat.NONE, + help="""[Only for LINUX] + {}: no timestamps. + {}: add timestamps with UNIX epoch time format. + {}: add timestamps with ISO time format. + """.format( + TimestampFormat.NONE, TimestampFormat.EPOCH, TimestampFormat.DATETIME + ), + ) + group.add_argument( + "-c", + "--count", + type=int, + help="""Stop after sending the count. + see also ping(8) [-c count] option description. + """, + ) + group.add_argument( + "-s", "--packet-size", type=int, help="Specifies the number of data bytes to be sent.", + ) + group.add_argument( + "--ttl", type=int, help="Specifies the Time to Live.", + ) + group.add_argument( + "-w", + "--deadline", + type=str, + help="""Timeout before ping exits. + valid time units are: {units}. if no unit string found, considered seconds as + the time unit. + + see also ping(8) [-w deadline] option description. + note: meaning of the 'deadline' may differ system to system. + """.format( + units=_get_unit_help_msg() + ), + ) + group.add_argument( + "--timeout", + type=str, + help="""Time to wait for a response per packet. + Valid time units are: {units}. if no unit string found, considered milliseconds as + the time unit. + Attempt to send packets with milliseconds granularity in default. + If the system does not support timeout in milliseconds, round up as seconds. + Use system default if not specified. + This option will be ignored if the system does not support timeout itself. + + See also ping(8) [-W timeout] option description. + note: meaning of the 'timeout' may differ system to system. + """.format( + units=_get_unit_help_msg() + ), + ) + group.add_argument("-I", "--interface", dest="interface", help="network interface") + + group = parser.add_argument_group("Output Options") # type: ignore + group.add_argument( + "--indent", + type=int, + default=4, + help="""JSON output will be pretty-printed with the indent level. + (default= %(default)s) + """, + ) + group.add_argument( + "--icmp-reply", + "--icmp-replies", + action="store_true", + default=False, + help="print results for each ICMP packet reply.", + ) + group.add_argument( + "--no-color", action="store_true", default=False, help="Turn off colors.", + ) + + loglevel_dest = "log_level" + group = parser.add_mutually_exclusive_group() # type: ignore + group.add_argument( + "--debug", + dest=loglevel_dest, + action="store_const", + const=LogLevel.DEBUG, + default=LogLevel.INFO, + help="for debug print.", + ) + group.add_argument( + "--quiet", + dest=loglevel_dest, + action="store_const", + const=QUIET_LOG_LEVEL, + default=LogLevel.INFO, + help="suppress execution log messages.", + ) + + return parser.parse_args() + + +def initialize_logger(log_level: str) -> None: + logger.remove() + + if log_level == QUIET_LOG_LEVEL: + set_logger(is_enable=False) + return + + if log_level == "DEBUG": + log_format = ( + "<level>{level: <8}</level> | " + "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>" + ) + + try: + import loguru # noqa + except ImportError: + print( + "required to install with 'pip install pingparsing[cli]' to debug print", + file=sys.stderr, + ) + else: + log_format = "<level>[{level}]</level> {message}" + + logger.add(sys.stdout, colorize=True, format=log_format, level=log_level, enqueue=True) + set_logger(is_enable=True) + + +def is_use_stdin() -> Tuple[bool, bool]: + if sys.stdin.isatty(): + return (False, False) + + found_stdin_specifier = "-" in sys.argv[1:] + + return (len(sys.argv) == 1 or found_stdin_specifier, found_stdin_specifier) + + +def parse_ping( + dest_or_file: str, + interface: Optional[str], + count: int, + packet_size: Optional[int], + ttl: Optional[int], + deadline: TimeArg, + timeout: TimeArg, + is_parse_icmp_reply: bool, + timestamp: str, +) -> Tuple[str, Any]: + if os.path.isfile(dest_or_file): + with open(dest_or_file) as f: + ping_result_text = f.read() + else: + transmitter = PingTransmitter() + transmitter.destination = dest_or_file + transmitter.interface = interface + transmitter.count = count + transmitter.packet_size = packet_size + transmitter.ttl = ttl + transmitter.deadline = deadline + transmitter.timeout = timeout + transmitter.is_quiet = not is_parse_icmp_reply + transmitter.timestamp = timestamp != TimestampFormat.NONE + + try: + result = transmitter.ping() + except CommandError as e: + logger.error(e) + sys.exit(e.errno) + + ping_result_text = result.stdout + if result.returncode != 0: + if result.stderr: + logger.error(result.stderr) + + ping_parser = PingParsing() + stats = ping_parser.parse(ping_result_text) + output = stats.as_dict(include_icmp_replies=is_parse_icmp_reply) + + return (dest_or_file, output) + + +def get_ping_param(options) -> Tuple: + count = options.count + deadline = options.deadline + timeout = options.timeout + + if not options.count and not options.deadline: + count = DEFAULT_COUNT + + return (count, deadline, timeout) + + +def print_result(text: str, colorize: bool) -> None: + if not sys.stdout.isatty() or not colorize: + # avoid to colorized when piped or redirected + print(text) + return + + try: + from pygments import highlight + from pygments.lexers import JsonLexer + from pygments.formatters import TerminalTrueColorFormatter + + print( + highlight( + code=text, lexer=JsonLexer(), formatter=TerminalTrueColorFormatter(style="monokai") + ).strip() + ) + except ImportError: + print(text) + + +def _serialize_epoch(obj): + if isinstance(obj, datetime): + return float(obj.strftime("%s.%f")) + + if isinstance(obj, TIMESTAMP_TYPES): + return obj + + raise TypeError("not supported type to convert: {}".format(type(obj))) + + +def _serialize_datetime(obj): + if isinstance(obj, datetime): + return obj.isoformat() + + if isinstance(obj, TIMESTAMP_TYPES): + return obj + + raise TypeError("not supported type to convert: {}".format(type(obj))) + + +timestamp_serialize_map = { + TimestampFormat.NONE: None, + TimestampFormat.EPOCH: _serialize_epoch, + TimestampFormat.DATETIME: _serialize_datetime, +} + + +def dumps_dict(obj: Dict, timestamp_format: str, indent: int = 0) -> str: + serialize_func = timestamp_serialize_map[timestamp_format] + + if indent <= 0: + return json.dumps(obj, default=serialize_func) + + return json.dumps(obj, indent=indent, default=serialize_func) + + +def main() -> int: + options = parse_option() + + initialize_logger(options.log_level) + + output = {} + use_stdin, found_stdin_specifier = is_use_stdin() + if not use_stdin and not found_stdin_specifier: + from concurrent import futures + + max_workers = ( + multiprocessing.cpu_count() * 2 if options.max_workers is None else options.max_workers + ) + count, deadline, timeout = get_ping_param(options) + logger.debug( + "max-workers={}, count={}, deadline={}, timeout={}".format( + max_workers, count, deadline, timeout + ) + ) + + try: + with futures.ProcessPoolExecutor(max_workers) as executor: + future_list = [] + for dest_or_file in options.destination_or_file: + future_list.append( + executor.submit( + parse_ping, + dest_or_file, + options.interface, + count, + options.packet_size, + options.ttl, + deadline, + timeout, + options.icmp_reply, + options.timestamp, + ) + ) + + for future in futures.as_completed(future_list): + key, ping_data = future.result() + output[key] = ping_data + finally: + executor.shutdown() + else: + ping_result_text = sys.stdin.read() + ping_parser = PingParsing() + stats = ping_parser.parse(ping_result_text) + output = stats.as_dict(include_icmp_replies=options.icmp_reply) + + print_result( + dumps_dict(output, timestamp_format=options.timestamp, indent=options.indent), + colorize=not options.no_color, + ) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/pingparsing/__version__.py new/pingparsing-1.0.2/pingparsing/__version__.py --- old/pingparsing-1.0.1/pingparsing/__version__.py 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/pingparsing/__version__.py 2020-04-04 12:15:05.000000000 +0200 @@ -1,6 +1,6 @@ __author__ = "Tsuyoshi Hombashi" __copyright__ = "Copyright 2016, {}".format(__author__) __license__ = "MIT License" -__version__ = "1.0.1" +__version__ = "1.0.2" __maintainer__ = __author__ __email__ = "tsuyoshi.homba...@gmail.com" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/pingparsing/cli.py new/pingparsing-1.0.2/pingparsing/cli.py --- old/pingparsing-1.0.1/pingparsing/cli.py 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/pingparsing/cli.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,391 +0,0 @@ -#!/usr/bin/env python3 - -""" -.. codeauthor:: Tsuyoshi Hombashi <tsuyoshi.homba...@gmail.com> -""" - -import argparse -import multiprocessing -import os -import sys -from datetime import datetime -from textwrap import dedent -from typing import Any, Dict, Optional, Tuple - -import humanreadable as hr -from subprocrunner import CommandError - -from pingparsing._logger import logger, set_logger - -from .__version__ import __version__ -from ._pingparsing import PingParsing -from ._pingtransmitter import PingTransmitter -from ._typing import TimeArg - - -try: - import simplejson as json -except ImportError: - import json # type: ignore - - -DEFAULT_COUNT = 10 -QUIET_LOG_LEVEL = "QUIET" -TIMESTAMP_TYPES = (int, float, str) - - -class TimestampFormat: - NONE = "none" - EPOCH = "epoch" - DATETIME = "datetime" - LIST = (NONE, EPOCH, DATETIME) - - -class LogLevel: - DEBUG = "DEBUG" - INFO = "INFO" - - -def _get_unit_help_msg() -> str: - return ", ".join(["/".join(values) for values in hr.Time.get_text_units().values()]) - - -def parse_option() -> argparse.Namespace: - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=dedent( - """\ - Documentation: https://pingparsing.rtfd.io/ - Issue tracker: https://github.com/thombashi/pingparsing/issues - """ - ), - ) - parser.add_argument( - "-V", "--version", action="version", version="%(prog)s {}".format(__version__) - ) - - use_stdin, found_stdin_specifier = is_use_stdin() - if not use_stdin or found_stdin_specifier: - parser.add_argument( - "destination_or_file", - nargs="+", - help="Destinations to send ping, or files to parse. '-' for parse the standard input.", - ) - - parser.add_argument( - "--max-workers", - type=int, - help="""Number of threads for when multiple destination/file - specified. defaults to equals to two times number of cores. - """, - ) - - group = parser.add_argument_group("Ping Options") # type: ignore - group.add_argument( - "--timestamp", - choices=TimestampFormat.LIST, - default=TimestampFormat.NONE, - help="""[Only for LINUX] - {}: no timestamps. - {}: add timestamps with UNIX epoch time format. - {}: add timestamps with ISO time format. - """.format( - TimestampFormat.NONE, TimestampFormat.EPOCH, TimestampFormat.DATETIME - ), - ) - group.add_argument( - "-c", - "--count", - type=int, - help="""Stop after sending the count. - see also ping(8) [-c count] option description. - """, - ) - group.add_argument( - "-s", "--packet-size", type=int, help="Specifies the number of data bytes to be sent.", - ) - group.add_argument( - "--ttl", type=int, help="Specifies the Time to Live.", - ) - group.add_argument( - "-w", - "--deadline", - type=str, - help="""Timeout before ping exits. - valid time units are: {units}. if no unit string found, considered seconds as - the time unit. - - see also ping(8) [-w deadline] option description. - note: meaning of the 'deadline' may differ system to system. - """.format( - units=_get_unit_help_msg() - ), - ) - group.add_argument( - "--timeout", - type=str, - help="""Time to wait for a response per packet. - Valid time units are: {units}. if no unit string found, considered milliseconds as - the time unit. - Attempt to send packets with milliseconds granularity in default. - If the system does not support timeout in milliseconds, round up as seconds. - Use system default if not specified. - This option will be ignored if the system does not support timeout itself. - - See also ping(8) [-W timeout] option description. - note: meaning of the 'timeout' may differ system to system. - """.format( - units=_get_unit_help_msg() - ), - ) - group.add_argument("-I", "--interface", dest="interface", help="network interface") - - group = parser.add_argument_group("Output Options") # type: ignore - group.add_argument( - "--indent", - type=int, - default=4, - help="""JSON output will be pretty-printed with the indent level. - (default= %(default)s) - """, - ) - group.add_argument( - "--icmp-reply", - "--icmp-replies", - action="store_true", - default=False, - help="print results for each ICMP packet reply.", - ) - group.add_argument( - "--no-color", action="store_true", default=False, help="Turn off colors.", - ) - - loglevel_dest = "log_level" - group = parser.add_mutually_exclusive_group() # type: ignore - group.add_argument( - "--debug", - dest=loglevel_dest, - action="store_const", - const=LogLevel.DEBUG, - default=LogLevel.INFO, - help="for debug print.", - ) - group.add_argument( - "--quiet", - dest=loglevel_dest, - action="store_const", - const=QUIET_LOG_LEVEL, - default=LogLevel.INFO, - help="suppress execution log messages.", - ) - - return parser.parse_args() - - -def initialize_logger(log_level: str) -> None: - logger.remove() - - if log_level == QUIET_LOG_LEVEL: - set_logger(is_enable=False) - return - - if log_level == "DEBUG": - log_format = ( - "<level>{level: <8}</level> | " - "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>" - ) - - try: - import loguru # noqa - except ImportError: - print( - "required to install with 'pip install pingparsing[cli]' to debug print", - file=sys.stderr, - ) - else: - log_format = "<level>[{level}]</level> {message}" - - logger.add(sys.stdout, colorize=True, format=log_format, level=log_level, enqueue=True) - set_logger(is_enable=True) - - -def is_use_stdin() -> Tuple[bool, bool]: - if sys.stdin.isatty(): - return (False, False) - - found_stdin_specifier = "-" in sys.argv[1:] - - return (len(sys.argv) == 1 or found_stdin_specifier, found_stdin_specifier) - - -def parse_ping( - dest_or_file: str, - interface: Optional[str], - count: int, - packet_size: Optional[int], - ttl: Optional[int], - deadline: TimeArg, - timeout: TimeArg, - is_parse_icmp_reply: bool, - timestamp: str, -) -> Tuple[str, Any]: - if os.path.isfile(dest_or_file): - with open(dest_or_file) as f: - ping_result_text = f.read() - else: - transmitter = PingTransmitter() - transmitter.destination = dest_or_file - transmitter.interface = interface - transmitter.count = count - transmitter.packet_size = packet_size - transmitter.ttl = ttl - transmitter.deadline = deadline - transmitter.timeout = timeout - transmitter.is_quiet = not is_parse_icmp_reply - transmitter.timestamp = timestamp != TimestampFormat.NONE - - try: - result = transmitter.ping() - except CommandError as e: - logger.error(e) - sys.exit(e.errno) - - ping_result_text = result.stdout - if result.returncode != 0: - if result.stderr: - logger.error(result.stderr) - - ping_parser = PingParsing() - stats = ping_parser.parse(ping_result_text) - output = stats.as_dict(include_icmp_replies=is_parse_icmp_reply) - - return (dest_or_file, output) - - -def get_ping_param(options) -> Tuple: - count = options.count - deadline = options.deadline - timeout = options.timeout - - if not options.count and not options.deadline: - count = DEFAULT_COUNT - - return (count, deadline, timeout) - - -def print_result(text: str, colorize: bool) -> None: - if not sys.stdout.isatty() or not colorize: - # avoid to colorized when piped or redirected - print(text) - return - - try: - from pygments import highlight - from pygments.lexers import JsonLexer - from pygments.formatters import TerminalTrueColorFormatter - - print( - highlight( - code=text, lexer=JsonLexer(), formatter=TerminalTrueColorFormatter(style="monokai") - ).strip() - ) - except ImportError: - print(text) - - -def _serialize_epoch(obj): - if isinstance(obj, datetime): - return float(obj.strftime("%s.%f")) - - if isinstance(obj, TIMESTAMP_TYPES): - return obj - - raise TypeError("not supported type to convert: {}".format(type(obj))) - - -def _serialize_datetime(obj): - if isinstance(obj, datetime): - return obj.isoformat() - - if isinstance(obj, TIMESTAMP_TYPES): - return obj - - raise TypeError("not supported type to convert: {}".format(type(obj))) - - -timestamp_serialize_map = { - TimestampFormat.NONE: None, - TimestampFormat.EPOCH: _serialize_epoch, - TimestampFormat.DATETIME: _serialize_datetime, -} - - -def dumps_dict(obj: Dict, timestamp_format: str, indent: int = 0) -> str: - serialize_func = timestamp_serialize_map[timestamp_format] - - if indent <= 0: - return json.dumps(obj, default=serialize_func) - - return json.dumps(obj, indent=indent, default=serialize_func) - - -def main() -> int: - options = parse_option() - - initialize_logger(options.log_level) - - output = {} - use_stdin, found_stdin_specifier = is_use_stdin() - if not use_stdin and not found_stdin_specifier: - from concurrent import futures - - max_workers = ( - multiprocessing.cpu_count() * 2 if options.max_workers is None else options.max_workers - ) - count, deadline, timeout = get_ping_param(options) - logger.debug( - "max-workers={}, count={}, deadline={}, timeout={}".format( - max_workers, count, deadline, timeout - ) - ) - - try: - with futures.ProcessPoolExecutor(max_workers) as executor: - future_list = [] - for dest_or_file in options.destination_or_file: - future_list.append( - executor.submit( - parse_ping, - dest_or_file, - options.interface, - count, - options.packet_size, - options.ttl, - deadline, - timeout, - options.icmp_reply, - options.timestamp, - ) - ) - - for future in futures.as_completed(future_list): - key, ping_data = future.result() - output[key] = ping_data - finally: - executor.shutdown() - else: - ping_result_text = sys.stdin.read() - ping_parser = PingParsing() - stats = ping_parser.parse(ping_result_text) - output = stats.as_dict(include_icmp_replies=options.icmp_reply) - - print_result( - dumps_dict(output, timestamp_format=options.timestamp, indent=options.indent), - colorize=not options.no_color, - ) - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/requirements/requirements.txt new/pingparsing-1.0.2/requirements/requirements.txt --- old/pingparsing-1.0.1/requirements/requirements.txt 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/requirements/requirements.txt 2020-04-04 12:15:05.000000000 +0200 @@ -1,4 +1,4 @@ humanreadable>=0.1.0,<1 pyparsing>=2.0.3,<3 -subprocrunner>=1.1.0,<2 -typepy>=0.6.4,<2 +subprocrunner>=1.2.1,<2 +typepy>=1.0.0,<2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/setup.py new/pingparsing-1.0.2/setup.py --- old/pingparsing-1.0.1/setup.py 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/setup.py 2020-04-04 12:15:05.000000000 +0200 @@ -56,7 +56,7 @@ long_description=long_description, long_description_content_type="text/x-rst", packages=setuptools.find_packages(exclude=["test*"]), - package_data={"pingparsing": ["py.typed"]}, + package_data={MODULE_NAME: ["py.typed"]}, project_urls={ "Documentation": "https://{:s}.rtfd.io/".format(MODULE_NAME), "Source": REPOSITORY_URL, @@ -92,5 +92,5 @@ "Topic :: Text Processing", ], cmdclass=get_release_command_class(), - entry_points={"console_scripts": ["pingparsing=pingparsing.cli:main"]}, + entry_points={"console_scripts": ["pingparsing=pingparsing.__main__:main"]}, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/test/test_cli.py new/pingparsing-1.0.2/test/test_cli.py --- old/pingparsing-1.0.1/test/test_cli.py 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/test/test_cli.py 2020-04-04 12:15:05.000000000 +0200 @@ -2,6 +2,7 @@ .. codeauthor:: Tsuyoshi Hombashi <tsuyoshi.homba...@gmail.com> """ +import sys from textwrap import dedent import pytest @@ -26,13 +27,15 @@ tmp_ping_file.write(DEBIAN_SUCCESS_0.value) tmp_ping_path = str(tmp_ping_file) - runner = SubprocessRunner(["pingparsing", tmp_ping_path]) + runner = SubprocessRunner([sys.executable, "-m", "pingparsing", tmp_ping_path]) runner.run() print_result(stdout=runner.stdout, stderr=runner.stderr) assert runner.returncode == 0 assert json.loads(runner.stdout)[tmp_ping_path] == DEBIAN_SUCCESS_0.expected - runner = SubprocessRunner(["pingparsing", tmp_ping_path, "--no-color"]) + runner = SubprocessRunner( + [sys.executable, "-m", "pingparsing", tmp_ping_path, "--no-color"] + ) runner.run() print_result(stdout=runner.stdout, stderr=runner.stderr) assert runner.returncode == 0 @@ -47,7 +50,9 @@ tmp_ping_file_win.write(WINDOWS7SP1_SUCCESS.value) tmp_ping_path_win = str(tmp_ping_file_win) - runner = SubprocessRunner(["pingparsing", tmp_ping_path_deb, tmp_ping_path_win]) + runner = SubprocessRunner( + [sys.executable, "-m", "pingparsing", tmp_ping_path_deb, tmp_ping_path_win] + ) runner.run() print_result(stdout=runner.stdout, stderr=runner.stderr) @@ -62,7 +67,7 @@ @pytest.mark.xfail(run=False) class Test_cli_pipe: def test_normal(self, tmpdir): - runner = SubprocessRunner(["pingparsing"]) + runner = SubprocessRunner([sys.executable, "-m", "pingparsing"]) runner.run(input=DEBIAN_SUCCESS_0.value) print_result(stdout=runner.stdout, stderr=runner.stderr) @@ -108,7 +113,7 @@ } """ ) - runner = SubprocessRunner(["pingparsing", "-", "--icmp-reply"]) + runner = SubprocessRunner([sys.executable, "-m", "pingparsing", "-", "--icmp-reply"]) runner.run(input=UBUNTU_SUCCESS_2.value) print_result(stdout=runner.stdout, stderr=runner.stderr, expected=expected) @@ -122,7 +127,7 @@ def test_normal_single(self): count = 1 dest = "localhost" - runner = SubprocessRunner(["pingparsing", dest, "-c", count]) + runner = SubprocessRunner([sys.executable, "-m", "pingparsing", dest, "-c", count]) runner.run() print_result(stdout=runner.stdout, stderr=runner.stderr) @@ -137,7 +142,7 @@ def test_normal_multi(self): count = 1 dest_list = ["google.com", "twitter.com"] - runner = SubprocessRunner(["pingparsing"] + dest_list + ["-c", count]) + runner = SubprocessRunner([sys.executable, "-m", "pingparsing"] + dest_list + ["-c", count]) runner.run() print_result(stdout=runner.stdout, stderr=runner.stderr) @@ -153,7 +158,17 @@ count = 1 dest = "localhost" runner = SubprocessRunner( - ["pingparsing", dest, "-c", count, "--icmp-reply", "--timestamp", "epoch"] + [ + sys.executable, + "-m", + "pingparsing", + dest, + "-c", + count, + "--icmp-reply", + "--timestamp", + "epoch", + ] ) runner.run() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pingparsing-1.0.1/tox.ini new/pingparsing-1.0.2/tox.ini --- old/pingparsing-1.0.1/tox.ini 2020-02-23 17:27:00.000000000 +0100 +++ new/pingparsing-1.0.2/tox.ini 2020-04-04 12:15:05.000000000 +0200 @@ -27,11 +27,10 @@ python setup.py clean --all [testenv:clean] -basepython = python3.8 deps = cleanpy commands = - cleanpy --all . + cleanpy --all --exclude-envs . [testenv:cov] deps = @@ -85,6 +84,6 @@ [testenv:release] basepython = python3.8 deps = - releasecmd>=0.2.0 + releasecmd>=0.3.1,<1 commands = python setup.py release --sign {posargs}