diff --git a/CHANGELOG b/CHANGELOG index 9f30bcf8..19c37f84 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ jc changelog +20210520 v1.15.5 +- Fix issue where help and about information would not display if a 3rd party parser library was missing. (e.g. xmltodict) +- Add more error message detail when encountering ParseError and LibraryNotFound exceptions + 20210517 v1.15.4 - Update ping parser to support error responses in OSX and BSD - Update ping parser to be more resilient against parsing errors for unknown error types diff --git a/README.md b/README.md index 4bac69df..5c5cc4eb 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Use Cases: - [Nornir command output parsing](https://blog.kellybrazil.com/2020/12/09/parsing-command-output-in-nornir-with-jc/) ## Installation -There are several ways to get `jc`. You can install via `pip`; other OS package repositories like `apt-get`, `dnf`, `zypper`, `pacman`, `nix-env`, `guix`, `brew`, or `portsnap`; via DEB/RPM packaged binaries; or by downloading the correct binary for your architecture and running it anywhere on your filesystem. +There are several ways to get `jc`. You can install via `pip`; other OS package repositories like `apt-get`, `dnf`, `zypper`, `pacman`, `nix-env`, `guix`, `brew`, or `portsnap`; via DEB, RPM, and MSI packaged binaries for linux and Windows; or by downloading the correct binary for your architecture and running it anywhere on your filesystem. ### Pip (macOS, linux, unix, Windows) ```bash @@ -248,7 +248,7 @@ Local plugin filenames must be valid python module names, therefore must consist ### Caveats **Locale:** -For best results set the `LANG` locale environment variable to `C`. For example, either by setting directly on the command-line: +For best results set the `LANG` locale environment variable to `C` or `en_US.UTF-8`. For example, either by setting directly on the command-line: ``` $ LANG=C date | jc --date ``` @@ -266,11 +266,16 @@ If a UTC timezone can be detected in the text of the command output, the timesta ## Compatibility Some parsers like `dig`, `xml`, `csv`, etc. will work on any platform. Other parsers that convert platform-specific output will generate a warning message if they are run on an unsupported platform. To see all parser information, including compatibility, run `jc -ap`. -You may still use a parser on an unsupported platform - for example, you may want to parse a file with linux `lsof` output on an macOS laptop. In that case you can suppress the warning message with the `-q` cli option or the `quiet=True` function parameter in `parse()`: +You may still use a parser on an unsupported platform - for example, you may want to parse a file with linux `lsof` output on an macOS or Windows laptop. In that case you can suppress the warning message with the `-q` cli option or the `quiet=True` function parameter in `parse()`: +macOS: ```bash cat lsof.out | jc --lsof -q ``` +or Windows: +```bash +type lsof.out | jc --lsof -q +``` Tested on: - Centos 7.7 @@ -282,6 +287,8 @@ Tested on: - NixOS - FreeBSD12 - Windows 10 +- Windows 2016 Server +- Windows 2019 Server ## Contributions Feel free to add/improve code or parsers! You can use the [`jc/parsers/foo.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo.py) parser as a template and submit your parser with a pull request. diff --git a/docs/parsers/xml.md b/docs/parsers/xml.md index 9393291a..6be25da5 100644 --- a/docs/parsers/xml.md +++ b/docs/parsers/xml.md @@ -95,4 +95,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, cygwin, win32, aix, freebsd -Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/yaml.md b/docs/parsers/yaml.md index 36a6d1f0..d389c3ec 100644 --- a/docs/parsers/yaml.md +++ b/docs/parsers/yaml.md @@ -109,4 +109,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, cygwin, win32, aix, freebsd -Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/jc/__init__.py b/jc/__init__.py index 0c8ac89a..6e6938ff 100644 --- a/jc/__init__.py +++ b/jc/__init__.py @@ -86,4 +86,4 @@ Module Example: """ name = 'jc' -__version__ = '1.15.4' +__version__ = '1.15.5' diff --git a/jc/cli.py b/jc/cli.py index e11b09b3..14f7b983 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -16,6 +16,7 @@ import jc import jc.appdirs as appdirs import jc.utils import jc.tracebackplus +from jc.exceptions import LibraryNotInstalled, ParseError # make pygments import optional try: @@ -603,6 +604,16 @@ def main(): try: result = parser.parse(data, raw=raw, quiet=quiet) + except (ParseError, LibraryNotInstalled) as e: + if debug: + raise + else: + jc.utils.error_message( + f'Parser issue with {parser_name}:\n' + f' {e}\n' + ' For details use the -d or -dd option. Use "jc -h" for help.') + sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) + except Exception: if debug: raise diff --git a/jc/exceptions.py b/jc/exceptions.py index f7dd2571..32218db6 100644 --- a/jc/exceptions.py +++ b/jc/exceptions.py @@ -3,3 +3,7 @@ class ParseError(Exception): pass + + +class LibraryNotInstalled(Exception): + pass diff --git a/jc/man/jc.1.gz b/jc/man/jc.1.gz index 967b30c9..b7b4c49b 100644 Binary files a/jc/man/jc.1.gz and b/jc/man/jc.1.gz differ diff --git a/jc/parsers/xml.py b/jc/parsers/xml.py index e662f7d4..6db0b590 100644 --- a/jc/parsers/xml.py +++ b/jc/parsers/xml.py @@ -65,19 +65,13 @@ Examples: ... } """ -import sys import jc.utils -# check if xml library is installed and fail gracefully if it is not -try: - import xmltodict -except Exception: - jc.utils.error_message('The xmltodict library is not installed.') - sys.exit(1) +from jc.exceptions import LibraryNotInstalled class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.4' + version = '1.5' description = 'XML file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -121,6 +115,12 @@ def parse(data, raw=False, quiet=False): Dictionary. Raw or processed structured data. """ + # check if xml library is installed and fail gracefully if it is not + try: + import xmltodict + except Exception: + raise LibraryNotInstalled('The xmltodict library is not installed.') + if not quiet: jc.utils.compatibility(__name__, info.compatible) diff --git a/jc/parsers/yaml.py b/jc/parsers/yaml.py index f25294e0..bfcbe85a 100644 --- a/jc/parsers/yaml.py +++ b/jc/parsers/yaml.py @@ -79,19 +79,13 @@ Examples: } ] """ -import sys import jc.utils -# check if yaml library is installed and fail gracefully if it is not -try: - from ruamel.yaml import YAML -except Exception: - jc.utils.error_message('The ruamel.yaml library is not installed.') - sys.exit(1) +from jc.exceptions import LibraryNotInstalled class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.4' + version = '1.5' description = 'YAML file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -135,6 +129,12 @@ def parse(data, raw=False, quiet=False): List of Dictionaries representing the YAML documents. """ + # check if yaml library is installed and fail gracefully if it is not + try: + from ruamel.yaml import YAML + except Exception: + raise LibraryNotInstalled('The ruamel.yaml library is not installed.') + if not quiet: jc.utils.compatibility(__name__, info.compatible) diff --git a/man/jc.1.gz b/man/jc.1.gz index 967b30c9..b7b4c49b 100644 Binary files a/man/jc.1.gz and b/man/jc.1.gz differ diff --git a/setup.py b/setup.py index 6dd19f30..325f8141 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open('README.md', 'r') as f: setuptools.setup( name='jc', - version='1.15.4', + version='1.15.5', author='Kelly Brazil', author_email='kellyjonbrazil@gmail.com', description='Converts the output of popular command-line tools and file-types to JSON.', diff --git a/templates/manpage_template b/templates/manpage_template index ecdc814e..2f30969b 100644 --- a/templates/manpage_template +++ b/templates/manpage_template @@ -112,7 +112,7 @@ Local plugin filenames must be valid python module names, therefore must consist Note: The application data directory follows the XDG Base Directory Specification .SH CAVEATS -\fBLocale:\fP For best results set the \fBLANG\fP locale environment variable to \fBC\fP. For example, either by setting directly on the command-line: +\fBLocale:\fP For best results set the \fBLANG\fP locale environment variable to \fBC\fP or \fBen_US.UTF-8\fP. For example, either by setting directly on the command-line: \fB$ LANG=C date | jc --date\fP diff --git a/templates/readme_template b/templates/readme_template index d1f6cfa6..4a54f11b 100644 --- a/templates/readme_template +++ b/templates/readme_template @@ -83,7 +83,7 @@ Use Cases: - [Nornir command output parsing](https://blog.kellybrazil.com/2020/12/09/parsing-command-output-in-nornir-with-jc/) ## Installation -There are several ways to get `jc`. You can install via `pip`; other OS package repositories like `apt-get`, `dnf`, `zypper`, `pacman`, `nix-env`, `guix`, `brew`, or `portsnap`; via DEB/RPM packaged binaries; or by downloading the correct binary for your architecture and running it anywhere on your filesystem. +There are several ways to get `jc`. You can install via `pip`; other OS package repositories like `apt-get`, `dnf`, `zypper`, `pacman`, `nix-env`, `guix`, `brew`, or `portsnap`; via DEB, RPM, and MSI packaged binaries for linux and Windows; or by downloading the correct binary for your architecture and running it anywhere on your filesystem. ### Pip (macOS, linux, unix, Windows) ```bash @@ -176,7 +176,7 @@ Local plugin filenames must be valid python module names, therefore must consist ### Caveats **Locale:** -For best results set the `LANG` locale environment variable to `C`. For example, either by setting directly on the command-line: +For best results set the `LANG` locale environment variable to `C` or `en_US.UTF-8`. For example, either by setting directly on the command-line: ``` $ LANG=C date | jc --date ``` @@ -194,11 +194,16 @@ If a UTC timezone can be detected in the text of the command output, the timesta ## Compatibility Some parsers like `dig`, `xml`, `csv`, etc. will work on any platform. Other parsers that convert platform-specific output will generate a warning message if they are run on an unsupported platform. To see all parser information, including compatibility, run `jc -ap`. -You may still use a parser on an unsupported platform - for example, you may want to parse a file with linux `lsof` output on an macOS laptop. In that case you can suppress the warning message with the `-q` cli option or the `quiet=True` function parameter in `parse()`: +You may still use a parser on an unsupported platform - for example, you may want to parse a file with linux `lsof` output on an macOS or Windows laptop. In that case you can suppress the warning message with the `-q` cli option or the `quiet=True` function parameter in `parse()`: +macOS: ```bash cat lsof.out | jc --lsof -q ``` +or Windows: +```bash +type lsof.out | jc --lsof -q +``` Tested on: - Centos 7.7 @@ -210,6 +215,8 @@ Tested on: - NixOS - FreeBSD12 - Windows 10 +- Windows 2016 Server +- Windows 2019 Server ## Contributions Feel free to add/improve code or parsers! You can use the [`jc/parsers/foo.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo.py) parser as a template and submit your parser with a pull request. diff --git a/tests/test_utils.py b/tests/test_utils.py index bc1ea123..45aa738d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -18,6 +18,8 @@ class MyTests(unittest.TestCase): '3/22/2021, 1:15:51 PM (UTC-0600)': {'string': '3/22/2021, 1:15:51 PM (UTC-0600)', 'format': 1700, 'naive': 1616444151, 'utc': None}, # Windows english format with UTC tz (found in systeminfo cli output) '3/22/2021, 1:15:51 PM (UTC)': {'string': '3/22/2021, 1:15:51 PM (UTC)', 'format': 1705, 'naive': 1616444151, 'utc': 1616418951}, + # Windows english format with UTC tz in long-form (found in systeminfo cli output) + '3/22/2021, 1:15:51 PM (Coordinated Universal Time)': {'string': '3/22/2021, 1:15:51 PM (Coordinated Universal Time)', 'format': 1705, 'naive': 1616444151, 'utc': 1616418951}, # Windows english format with UTC tz (found in systeminfo cli output) '3/22/2021, 1:15:51 PM (UTC+0000)': {'string': '3/22/2021, 1:15:51 PM (UTC+0000)', 'format': 1710, 'naive': 1616444151, 'utc': 1616418951}, # en_US.UTF-8 local format (found in upower cli output)