mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2026-04-03 17:44:07 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5344883394 | ||
|
|
3fcd2f6c2e | ||
|
|
f3d84bd5bf | ||
|
|
549780c232 | ||
|
|
2a6da69b82 | ||
|
|
5c538816cf | ||
|
|
7b8b378a7d |
@@ -1,5 +1,12 @@
|
||||
jc changelog
|
||||
|
||||
20200805 v1.13.4
|
||||
- Update crontab and crontab-u parsers to tighten up variable detection
|
||||
- Update ping parser to tighten linux/bsd detection
|
||||
|
||||
20200804 v1.13.3
|
||||
- Update ping parser for Raspberry Pi compatibility
|
||||
|
||||
20200803 v1.13.2
|
||||
- Add key/value file parser (wrapper for ini parser)
|
||||
- Add date command parser
|
||||
|
||||
@@ -79,7 +79,7 @@ See also:
|
||||
- [blog: linux apps should have a json flag](https://thomashunter.name/posts/2012-06-06-linux-cli-apps-should-have-a-json-flag)
|
||||
|
||||
## Installation
|
||||
There are several ways to get `jc`. You can install via `pip`; other OS package repositories like `dnf`, `zypper`, `pacman`, `nix-env`, `guix`, `brew`, or `portsnap`; via DEB/RPM packages; 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 packages; or by downloading the correct binary for your architecture and running it anywhere on your filesystem.
|
||||
|
||||
### Pip (macOS, linux, unix, Windows)
|
||||
```bash
|
||||
@@ -90,6 +90,7 @@ pip3 install jc
|
||||
|
||||
| OS | Command |
|
||||
|-----------------------|-------------------------------------------------------------------------------|
|
||||
| Debian linux | `apt-get install jc` |
|
||||
| Fedora linux | `dnf install jc` |
|
||||
| openSUSE linux | `zypper install jc` |
|
||||
| Arch linux | `pacman -S jc` |
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/bin/bash
|
||||
# Generate docs.md
|
||||
# requires pydoc-markdown 2.1.0.post1
|
||||
|
||||
cd jc
|
||||
pydocmd simple jc+ > ../docs/readme.md
|
||||
|
||||
@@ -21,7 +21,7 @@ import jc.appdirs as appdirs
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.13.2'
|
||||
version = '1.13.4'
|
||||
description = 'JSON CLI output utility'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
@@ -235,7 +235,7 @@ def parse(data, raw=False, quiet=False):
|
||||
# Pop any variable assignment lines
|
||||
cron_var = []
|
||||
for i, line in reversed(list(enumerate(cleandata))):
|
||||
if '=' in line:
|
||||
if '=' in line and not line.strip()[0].isdigit() and not line.strip()[0] == '@':
|
||||
var_line = cleandata.pop(i)
|
||||
var_name = var_line.split('=', maxsplit=1)[0].strip()
|
||||
var_value = var_line.split('=', maxsplit=1)[1].strip()
|
||||
|
||||
@@ -133,7 +133,7 @@ import jc.parsers.universal
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.3'
|
||||
version = '1.5'
|
||||
description = 'crontab file parser with user support'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -236,7 +236,7 @@ def parse(data, raw=False, quiet=False):
|
||||
# Pop any variable assignment lines
|
||||
cron_var = []
|
||||
for i, line in reversed(list(enumerate(cleandata))):
|
||||
if '=' in line:
|
||||
if '=' in line and not line.strip()[0].isdigit() and not line.strip()[0] == '@':
|
||||
var_line = cleandata.pop(i)
|
||||
var_name = var_line.split('=', maxsplit=1)[0].strip()
|
||||
var_value = var_line.split('=', maxsplit=1)[1].strip()
|
||||
|
||||
@@ -108,7 +108,7 @@ import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
version = '1.2'
|
||||
description = 'ping command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -496,7 +496,7 @@ def parse(data, raw=False, quiet=False):
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
if 'time' in data.splitlines()[-2]:
|
||||
if ' time ' in data.splitlines()[-2] or ' time ' in data.splitlines()[-3]:
|
||||
raw_output = linux_parse(data)
|
||||
else:
|
||||
raw_output = bsd_parse(data)
|
||||
|
||||
2
setup.py
2
setup.py
@@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
|
||||
|
||||
setuptools.setup(
|
||||
name='jc',
|
||||
version='1.13.2',
|
||||
version='1.13.4',
|
||||
author='Kelly Brazil',
|
||||
author_email='kellyjonbrazil@gmail.com',
|
||||
description='Converts the output of popular command-line tools and file-types to JSON.',
|
||||
|
||||
1
tests/fixtures/debian10/crontab-u.json
vendored
Normal file
1
tests/fixtures/debian10/crontab-u.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"variables": [], "schedule": [{"minute": ["30"], "hour": ["3"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["0"], "user": "root", "command": "test -e /run/systemd/system || SERVICE_MODE=1 /usr/lib/x86_64-linux-gnu/e2fsprogs/e2scrub_all_cron"}, {"minute": ["10"], "hour": ["3"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "user": "root", "command": "test -e /run/systemd/system || SERVICE_MODE=1 /sbin/e2scrub_all -A -r"}]}
|
||||
2
tests/fixtures/debian10/crontab-u.out
vendored
Normal file
2
tests/fixtures/debian10/crontab-u.out
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
30 3 * * 0 root test -e /run/systemd/system || SERVICE_MODE=1 /usr/lib/x86_64-linux-gnu/e2fsprogs/e2scrub_all_cron
|
||||
10 3 * * * root test -e /run/systemd/system || SERVICE_MODE=1 /sbin/e2scrub_all -A -r
|
||||
1
tests/fixtures/pi/ping-ip-O-D.json
vendored
Normal file
1
tests/fixtures/pi/ping-ip-O-D.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"destination_ip": "192.168.120.164", "data_bytes": 56, "pattern": null, "destination": "192.168.120.164", "packets_transmitted": 5, "packets_received": 0, "packet_loss_percent": 100.0, "duplicates": 0, "time_ms": 4154.0, "responses": [{"type": "timeout", "timestamp": 1596585008.591169, "icmp_seq": 1}, {"type": "timeout", "timestamp": 1596585009.631169, "icmp_seq": 2}, {"type": "timeout", "timestamp": 1596585010.671173, "icmp_seq": 3}, {"type": "timeout", "timestamp": 1596585011.711167, "icmp_seq": 4}]}
|
||||
10
tests/fixtures/pi/ping-ip-O-D.out
vendored
Normal file
10
tests/fixtures/pi/ping-ip-O-D.out
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
PING 192.168.120.164 (192.168.120.164) 56(84) bytes of data.
|
||||
[1596585008.591169] no answer yet for icmp_seq=1
|
||||
[1596585009.631169] no answer yet for icmp_seq=2
|
||||
[1596585010.671173] no answer yet for icmp_seq=3
|
||||
[1596585011.711167] no answer yet for icmp_seq=4
|
||||
|
||||
--- 192.168.120.164 ping statistics ---
|
||||
5 packets transmitted, 0 received, 100% packet loss, time 4154ms
|
||||
|
||||
|
||||
1
tests/fixtures/pi/ping-ip-O.json
vendored
Normal file
1
tests/fixtures/pi/ping-ip-O.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"destination_ip": "192.168.120.164", "data_bytes": 56, "pattern": null, "destination": "192.168.120.164", "packets_transmitted": 5, "packets_received": 0, "packet_loss_percent": 100.0, "duplicates": 0, "time_ms": 4149.0, "responses": [{"type": "timeout", "timestamp": null, "icmp_seq": 1}, {"type": "timeout", "timestamp": null, "icmp_seq": 2}, {"type": "timeout", "timestamp": null, "icmp_seq": 3}, {"type": "timeout", "timestamp": null, "icmp_seq": 4}]}
|
||||
10
tests/fixtures/pi/ping-ip-O.out
vendored
Normal file
10
tests/fixtures/pi/ping-ip-O.out
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
PING 192.168.120.164 (192.168.120.164) 56(84) bytes of data.
|
||||
no answer yet for icmp_seq=1
|
||||
no answer yet for icmp_seq=2
|
||||
no answer yet for icmp_seq=3
|
||||
no answer yet for icmp_seq=4
|
||||
|
||||
--- 192.168.120.164 ping statistics ---
|
||||
5 packets transmitted, 0 received, 100% packet loss, time 4149ms
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ class MyTests(unittest.TestCase):
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/crontab-u.out'), 'r', encoding='utf-8') as f:
|
||||
self.centos_7_7_crontab_u = f.read()
|
||||
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/debian10/crontab-u.out'), 'r', encoding='utf-8') as f:
|
||||
self.debian10_crontab_u = f.read()
|
||||
|
||||
# output
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/crontab-u.json'), 'r', encoding='utf-8') as f:
|
||||
self.ubuntu_18_4_crontab_u_json = json.loads(f.read())
|
||||
@@ -23,6 +26,9 @@ class MyTests(unittest.TestCase):
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/crontab-u.json'), 'r', encoding='utf-8') as f:
|
||||
self.centos_7_7_crontab_u_json = json.loads(f.read())
|
||||
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/debian10/crontab-u.json'), 'r', encoding='utf-8') as f:
|
||||
self.debian10_crontab_u_json = json.loads(f.read())
|
||||
|
||||
def test_crontab_u_nodata(self):
|
||||
"""
|
||||
Test 'crontab' with no data (has a user field)
|
||||
@@ -41,6 +47,12 @@ class MyTests(unittest.TestCase):
|
||||
"""
|
||||
self.assertEqual(jc.parsers.crontab_u.parse(self.centos_7_7_crontab_u, quiet=True), self.centos_7_7_crontab_u_json)
|
||||
|
||||
def test_crontab_u_debian10(self):
|
||||
"""
|
||||
Test 'crontab' on Debian10 (has a user field)
|
||||
"""
|
||||
self.assertEqual(jc.parsers.crontab_u.parse(self.debian10_crontab_u, quiet=True), self.debian10_crontab_u_json)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -181,6 +181,13 @@ class MyTests(unittest.TestCase):
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/ping6-ip-dup.out'), 'r', encoding='utf-8') as f:
|
||||
self.osx_10_14_6_ping6_ip_dup = f.read()
|
||||
|
||||
# raspberry pi
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/pi/ping-ip-O.out'), 'r', encoding='utf-8') as f:
|
||||
self.pi_ping_ip_O = f.read()
|
||||
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/pi/ping-ip-O-D.out'), 'r', encoding='utf-8') as f:
|
||||
self.pi_ping_ip_O_D = f.read()
|
||||
|
||||
# output
|
||||
|
||||
# centos
|
||||
@@ -353,6 +360,13 @@ class MyTests(unittest.TestCase):
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/ping6-ip-dup.json'), 'r', encoding='utf-8') as f:
|
||||
self.osx_10_14_6_ping6_ip_dup_json = json.loads(f.read())
|
||||
|
||||
# raspberry pi
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/pi/ping-ip-O.json'), 'r', encoding='utf-8') as f:
|
||||
self.pi_ping_ip_O_json = json.loads(f.read())
|
||||
|
||||
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/pi/ping-ip-O-D.json'), 'r', encoding='utf-8') as f:
|
||||
self.pi_ping_ip_O_D_json = json.loads(f.read())
|
||||
|
||||
def test_ping_nodata(self):
|
||||
"""
|
||||
Test 'ping' with no data
|
||||
@@ -689,6 +703,18 @@ class MyTests(unittest.TestCase):
|
||||
"""
|
||||
self.assertEqual(jc.parsers.ping.parse(self.osx_10_14_6_ping6_ip_dup, quiet=True), self.osx_10_14_6_ping6_ip_dup_json)
|
||||
|
||||
def test_ping_ip_O_pi(self):
|
||||
"""
|
||||
Test 'ping6 <ip> -O' on raspberry pi
|
||||
"""
|
||||
self.assertEqual(jc.parsers.ping.parse(self.pi_ping_ip_O, quiet=True), self.pi_ping_ip_O_json)
|
||||
|
||||
def test_ping_ip_O_D_pi(self):
|
||||
"""
|
||||
Test 'ping6 <ip> -O -D' on raspberry pi
|
||||
"""
|
||||
self.assertEqual(jc.parsers.ping.parse(self.pi_ping_ip_O_D, quiet=True), self.pi_ping_ip_O_D_json)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user