1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2026-04-03 17:44:07 +02:00

Compare commits

...

315 Commits

Author SHA1 Message Date
Kelly Brazil
b0d6a7307c Merge pull request #353 from kellyjonbrazil/dev
Dev v1.22.5
2023-01-11 14:39:13 -08:00
Kelly Brazil
53ad793ff8 doc update 2023-01-11 11:17:47 -08:00
Kelly Brazil
ea4332d8e4 add ini-dup tests 2023-01-10 16:06:05 -08:00
Kelly Brazil
5c5ff9324f update multi-line value behavior 2023-01-09 08:31:21 -08:00
Kelly Brazil
2ab6352fdb doc update 2023-01-08 19:54:32 -08:00
Kelly Brazil
56dcbaf40c doc update 2023-01-08 19:53:21 -08:00
Kelly Brazil
029b5abcac add ini-dup parser 2023-01-08 19:46:13 -08:00
Kelly Brazil
32521ac91a doc update 2023-01-08 10:55:48 -08:00
Kelly Brazil
bf88407902 remove special DEFAULT section handling 2023-01-08 10:55:44 -08:00
Kelly Brazil
63cf47db63 doc update 2023-01-06 13:37:34 -08:00
Kelly Brazil
9970866b3b Merge pull request #350 from davemq/arp_aix
AIX ARP support
2023-01-06 13:34:44 -08:00
Dave Marquardt
d61941b276 Merge branch 'dev' into arp_aix 2023-01-06 15:14:39 -06:00
Dave Marquardt
081fdb8026 Updated AIX ARP test comments 2023-01-06 15:13:03 -06:00
Dave Marquardt
f64dfbf79d Update comments about AIX ARP 2023-01-06 15:10:02 -06:00
Dave Marquardt
5fb73f4ad5 Added AIX support for ARP, along with AIX ARP test support 2023-01-06 14:53:50 -06:00
Dave Marquardt
1c16d32420 Added test data for AIX ARP 2023-01-06 14:51:09 -06:00
Kelly Brazil
e367e0d714 doc update 2023-01-06 09:28:13 -08:00
Kelly Brazil
4046649e32 toml tests and doc update 2023-01-06 09:11:00 -08:00
Kelly Brazil
77fcfe439c remove unused list 2023-01-06 08:50:03 -08:00
Kelly Brazil
71d1355419 formatting 2023-01-06 08:36:48 -08:00
Kelly Brazil
d1b270f336 formatting 2023-01-06 08:26:42 -08:00
Dave Marquardt
9190a08332 More AIX permanent ARP entry fixes 2023-01-06 10:25:04 -06:00
Dave Marquardt
3fae50e305 Handle permanent ARP entries on AIX 2023-01-06 10:21:32 -06:00
Dave Marquardt
3582497ed4 Fix interface parsing for incomplete ARP entry on AIX 2023-01-06 10:16:13 -06:00
Dave Marquardt
19a67daabf rewrite check for incomplete ARP entries 2023-01-06 10:12:50 -06:00
Dave Marquardt
02a7e5fd8a Updated ARP incomplete handling for AIX 2023-01-06 10:08:33 -06:00
Dave Marquardt
df72b16022 Start to fix AIX ARP support 2023-01-06 10:00:58 -06:00
Kelly Brazil
61bdc13810 doc update 2023-01-05 17:05:03 -08:00
Kelly Brazil
1350a34316 beautify process function 2023-01-05 16:59:22 -08:00
Kelly Brazil
7cfe68b96a beautify remove_quotes function 2023-01-05 16:55:53 -08:00
Kelly Brazil
7a93a61f54 move unsectioned k/v's to the top level 2023-01-05 15:44:21 -08:00
Kelly Brazil
362977e598 comment unused objects 2023-01-05 14:26:01 -08:00
Kelly Brazil
5cac897beb zipinfo fix for paths with spaces 2023-01-05 12:00:20 -08:00
Kelly Brazil
cad94cc6b3 formatting and doc update 2023-01-05 11:46:14 -08:00
Kelly Brazil
fe4e429e85 Merge pull request #349 from davemq/mount_aix
Add AIX mount support
2023-01-05 11:39:42 -08:00
Kelly Brazil
d83b10e2d5 doc update 2023-01-05 11:27:49 -08:00
Kelly Brazil
bd2a757fcd more refactoring 2023-01-05 11:27:00 -08:00
Dave Marquardt
358b69a4cb Merge branch 'dev' into mount_aix 2023-01-05 11:06:00 -06:00
Dave Marquardt
08821a1454 Removed unneeded imports from mount parser 2023-01-05 10:57:23 -06:00
Kelly Brazil
90277c1d87 formatting 2023-01-05 08:54:40 -08:00
Dave Marquardt
a51e702f77 Added AIX mount test 2023-01-05 10:53:02 -06:00
Dave Marquardt
466e37128b Merge branch 'dev' into mount_aix 2023-01-05 10:32:47 -06:00
Dave Marquardt
f1ea61388f Added AIX mount support 2023-01-05 10:28:01 -06:00
Kelly Brazil
72c11fda3a more refactoring 2023-01-05 08:00:18 -08:00
Kelly Brazil
d6645983ef more refactoring 2023-01-04 20:54:31 -08:00
Kelly Brazil
01e911ecdb remove more type annotations 2023-01-04 19:17:29 -08:00
Kelly Brazil
12c0b3d889 remove more type annotations 2023-01-04 19:13:12 -08:00
Kelly Brazil
c1075e40b7 remove more type hinting for python 3.6 2023-01-04 19:09:41 -08:00
Kelly Brazil
fabe3f01b7 remove type annotations for python 3.6 compatibility 2023-01-04 19:00:49 -08:00
Kelly Brazil
3a2ff61899 fix lsusb for extra hub port info and add videocontrol and videostreaming sections 2023-01-04 18:27:51 -08:00
Kelly Brazil
aeff94d272 add toml parser 2023-01-04 18:26:13 -08:00
Kelly Brazil
c94f5d83fa fix kv and ini parsers to only remove 1 quote from beginning and end 2023-01-03 13:26:52 -08:00
Kelly Brazil
b0756fa0f9 doc update 2023-01-03 13:05:51 -08:00
Kelly Brazil
6c85abd57b doc update 2023-01-03 13:04:13 -08:00
Kelly Brazil
7659ae94bd formatting 2023-01-03 12:59:10 -08:00
Kelly Brazil
e306e81e43 formatting 2023-01-03 12:57:04 -08:00
Kelly Brazil
6d5768b26b simplify code and doc update 2023-01-03 12:55:38 -08:00
Kelly Brazil
cee9f8bf32 remove duplicate code. add tests 2023-01-03 12:44:12 -08:00
Kelly Brazil
b8e2678c01 doc update 2023-01-03 12:30:23 -08:00
Kelly Brazil
b0fe96ed03 doc update 2023-01-03 12:28:26 -08:00
Kelly Brazil
bb65ec380b separate kv and ini parsers. add fake top-level section in ini files that are missing it. 2023-01-03 12:11:05 -08:00
Kelly Brazil
ae6248227b version bump 2023-01-03 11:53:57 -08:00
Kelly Brazil
36ce3c791d Merge pull request #343 from kellyjonbrazil/dev
Dev v1.22.4
2022-12-30 13:29:57 -08:00
Kelly Brazil
5d639db5a8 Merge branch 'master' into dev 2022-12-30 13:24:24 -08:00
Kelly Brazil
63161ffdbb doc update 2022-12-30 13:11:54 -08:00
Kelly Brazil
cf11c71831 move import to except block 2022-12-30 11:53:09 -08:00
Kelly Brazil
048f8c1f4b formatting 2022-12-30 11:49:20 -08:00
Kelly Brazil
b6b42d9071 doc update 2022-12-30 11:46:40 -08:00
Kelly Brazil
d43863ee9f delete the tempfile after use 2022-12-30 11:32:14 -08:00
Kelly Brazil
177d10577f create NamedTemporaryFile with delete=False for Windows compatibilty 2022-12-30 11:17:52 -08:00
Kelly Brazil
47d8e163de patch for windows compatibility: can only open tempfile once 2022-12-30 11:06:45 -08:00
Kelly Brazil
e49c621e59 try writing to file as bytes for windows compatibility 2022-12-30 10:44:46 -08:00
Kelly Brazil
5e32a6d828 fix for python 3.10+ compatibility 2022-12-30 10:37:12 -08:00
Kelly Brazil
b1358a7eca add nextstep plist support. using the pbPlist library 2022-12-30 10:27:03 -08:00
Kelly Brazil
ba89092e12 formatting 2022-12-29 14:52:33 -08:00
Kelly Brazil
f855420a82 doc update 2022-12-29 09:25:31 -08:00
Kelly Brazil
1589a81945 fix issue with text serial numbers in certificates 2022-12-28 21:59:38 -08:00
Kelly Brazil
eec2583cb2 formatting 2022-12-27 15:59:43 -08:00
Kelly Brazil
481c6a8de2 doc update 2022-12-27 14:01:03 -08:00
Kelly Brazil
68717e8493 add parser metadata tags and category view to help 2022-12-27 13:59:10 -08:00
Kelly Brazil
c524d37136 use ubuntu-20.04 instead of latest for python 3.6 2022-12-23 10:25:12 -08:00
Kelly Brazil
6674f549f2 version bumps and doc update 2022-12-23 10:14:19 -08:00
Kelly Brazil
ba371ec730 fix proc signature for pid_stat so hack comm names with parenthesis are handled correctly. 2022-12-23 10:08:19 -08:00
Kelly Brazil
44d1d52426 fix test for python 3.6 2022-12-23 09:40:26 -08:00
Kelly Brazil
edcca4fb96 remove re type annotations for python 3.6 compatibility 2022-12-23 09:23:51 -08:00
Kelly Brazil
6fbf9458d1 Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2022-12-23 09:21:29 -08:00
Kelly Brazil
a476e4639b force test 2022-12-23 09:21:27 -08:00
Kelly Brazil
5534a1c755 change to ubuntu-20.04 for python 3.6 tests 2022-12-23 09:20:32 -08:00
Kelly Brazil
c45518db70 Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2022-12-23 09:17:44 -08:00
Kelly Brazil
55480c059a python 3.6 compatibility: remove re.Match type annotation 2022-12-23 09:17:42 -08:00
Kelly Brazil
04a2af8681 add python 3.6 to tests 2022-12-23 09:14:19 -08:00
Kelly Brazil
71f672a0e0 add python 3.6 to tests 2022-12-23 09:13:00 -08:00
Kelly Brazil
33c40874fa version bump and add iwconfig parser 2022-12-23 09:12:09 -08:00
Kelly Brazil
b3ced64672 Merge pull request #334 from vrince/iwconfig-parser
add new iwconfig parser
2022-12-23 09:00:22 -08:00
Thomas Vincent
a60bf00d54 iwconfig: add test with many interface 2022-12-21 17:25:57 -05:00
Thomas Vincent
8d9a2744af iwconfig: add example in the docstring 2022-12-21 17:15:25 -05:00
Thomas Vincent
bcd7bac950 iwconfig: add to parser list + move test fixture to generic folder 2022-12-21 17:12:20 -05:00
Thomas Vincent
e996b3a9f6 add iwconfig raw vs process + tests 2022-12-19 22:36:48 -05:00
Thomas Vincent
e207cccdc5 fix copy/paste mess in regex 2022-12-19 22:23:10 -05:00
Thomas Vincent
9776dd1082 add new iwconfig parser 2022-12-19 22:13:58 -05:00
Kelly Brazil
bcff00799f Merge pull request #328 from kellyjonbrazil/dev
Dev v1.22.3
2022-12-16 15:31:16 -06:00
Kelly Brazil
0dc76621bc doc update 2022-12-16 12:54:07 -08:00
Kelly Brazil
1040c5706f split prefix and ports. remove utc timestamps 2022-12-14 11:55:46 -08:00
Kelly Brazil
265d08e3bd doc update 2022-12-13 17:32:12 -08:00
Kelly Brazil
491fce7052 add openvpn-status.log file parser 2022-12-13 17:31:05 -08:00
Kelly Brazil
3404bc4840 add pgpass tests 2022-12-13 14:57:22 -08:00
Kelly Brazil
064e3f6ac0 try changing test dates for windows compatibility 2022-12-13 14:11:12 -08:00
Kelly Brazil
71f0c4f9da doc update 2022-12-13 13:46:33 -08:00
Kelly Brazil
18143608dc doc update 2022-12-13 13:30:50 -08:00
Kelly Brazil
83a6d92449 fix tests for additional timestamps 2022-12-13 13:30:31 -08:00
Kelly Brazil
ac1f690c54 add epoch timestamps 2022-12-13 13:29:54 -08:00
Kelly Brazil
b063f1bfb4 add google big table time format 2022-12-13 13:10:34 -08:00
Kelly Brazil
4c5caa7b86 add iso attribute to timestamp 2022-12-13 12:47:31 -08:00
Kelly Brazil
85edda6e5f Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2022-12-13 12:15:28 -08:00
Kelly Brazil
6e1a4a103c formatting and typing fixes 2022-12-13 12:13:27 -08:00
Kelly Brazil
2879c084e5 doc update 2022-12-13 09:01:13 -08:00
Kelly Brazil
4ecc94e531 formatting and typing fixes 2022-12-13 09:01:04 -08:00
Kelly Brazil
b8ef583b93 Merge pull request #327 from graipher/master
Add parser for cbt
2022-12-13 10:40:46 -06:00
Andreas Weiden
fd61e19135 Add raw schema 2022-12-12 19:48:33 +01:00
Andreas Weiden
79011465af Fix docstring 2022-12-12 19:46:45 +01:00
Andreas Weiden
27acedf8b7 Add newlines at end of files 2022-12-12 15:43:27 +01:00
Andreas Weiden
532c37140c Move test stuff to fixtures 2022-12-12 15:33:40 +01:00
Andreas Weiden
7f4a951065 Add parser to table in readme 2022-12-12 15:18:39 +01:00
Andreas Weiden
b9fb7fad9c Add parser for cbt 2022-12-12 15:10:59 +01:00
Kelly Brazil
be85d78f55 doc update 2022-12-05 14:54:23 -08:00
Kelly Brazil
23e02090e0 add pgpass parser 2022-12-05 14:43:48 -08:00
Kelly Brazil
50f2a811ad doc update 2022-12-05 12:43:45 -08:00
Kelly Brazil
28ee448c44 remove unneeded type ignore comments 2022-12-05 12:42:55 -08:00
Kelly Brazil
688a2099b5 relax JSONDictType - unions and Dicts cause a lot of friction 2022-12-05 12:15:35 -08:00
Kelly Brazil
6f0a53ed02 fix doc title 2022-12-02 16:10:00 -08:00
Kelly Brazil
8a14de663e doc update 2022-12-02 15:16:46 -08:00
Kelly Brazil
09344e938a add lane info lines 2022-12-02 15:16:07 -08:00
Kelly Brazil
bf41140322 fix tests for missing ipv6 addresses 2022-12-02 11:16:13 -08:00
Kelly Brazil
689a85db9b fix for missing ipv6 addresses and scope_id 2022-12-02 11:09:17 -08:00
Kelly Brazil
5e0d206e7a minor cleanup 2022-11-22 13:18:08 -08:00
Kelly Brazil
61addd7950 doc update 2022-11-22 13:12:40 -08:00
Kelly Brazil
60bb9e2aa9 doc update 2022-11-22 13:11:41 -08:00
Kelly Brazil
842fbbab64 formatting 2022-11-22 13:11:10 -08:00
Kelly Brazil
bbd227caf4 tighten up blank line checking 2022-11-22 13:10:58 -08:00
Kelly Brazil
975b4f5e4f add clf-s parser tests 2022-11-22 13:10:15 -08:00
Kelly Brazil
06840931ba doc update 2022-11-21 16:54:42 -08:00
Kelly Brazil
9f4327f517 add clf-s streaming parser 2022-11-21 16:54:13 -08:00
Kelly Brazil
3f13c70dfa formatting 2022-11-21 12:12:16 -08:00
Kelly Brazil
26f8803b23 add support for unparsable lines 2022-11-21 12:09:19 -08:00
Kelly Brazil
60f1e79b2f fix clf request string parsing and add tests 2022-11-21 11:00:58 -08:00
Kelly Brazil
5ab2ebe45a add CLF timestamp support 2022-11-21 09:27:37 -08:00
Kelly Brazil
9c8fe80d6d add more processing and timestamp 2022-11-21 09:27:21 -08:00
Kelly Brazil
1e7e22330f doc update 2022-11-20 20:45:22 -08:00
Kelly Brazil
7244868fbd initial common log format parser 2022-11-20 20:43:49 -08:00
Kelly Brazil
86ed39ecdd tighten up efi split 2022-11-18 16:19:55 -08:00
Kelly Brazil
94d87b726f add efi partition split 2022-11-18 14:20:18 -08:00
Kelly Brazil
0984a1ec26 fix git-log tests and docs 2022-11-18 13:54:59 -08:00
Kelly Brazil
de5da060ce Merge pull request #322 from adamwolf/git-log-blank-author
Fix git log parsing with empty name or email
2022-11-18 13:18:06 -06:00
Kelly Brazil
592435572c Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev
add in PR 323
2022-11-18 11:11:57 -08:00
Kelly Brazil
3172a18a46 Merge pull request #323 from kianmeng/fix-typos
Fix typos
2022-11-18 13:05:36 -06:00
Kelly Brazil
7f1c57b89c version bump 2022-11-17 13:39:59 -06:00
Kian-Meng Ang
39555a48b5 Fix typos
Found via `codespell -S ./tests/fixtures -L
chage,ro,ist,ans,unx,respons,technik`
2022-11-16 10:01:58 +08:00
Adam Wolf
e4cdfa13ca Fix git log parsing with empty name or email
Sometimes, folks leave their name or email blank in on their
git commits.  Previously, a blank name crashed the git log
parser.
2022-11-11 13:33:01 -06:00
Kelly Brazil
cb4011bc03 formatting 2022-11-08 14:23:32 -08:00
Kelly Brazil
299b0faf7c Merge pull request #319 from kellyjonbrazil/dev
Dev v1.22.2
2022-11-08 16:32:03 +00:00
Kelly Brazil
2ffd698c03 update du docs 2022-11-08 08:13:41 -08:00
Kelly Brazil
dde54690fc Merge pull request #318 from kellyjonbrazil/master
sync to dev
2022-11-08 16:07:56 +00:00
Kelly Brazil
8d03055b34 add tests 2022-11-07 16:41:13 -08:00
Kelly Brazil
8a850be857 doc update 2022-11-07 13:26:16 -08:00
Kelly Brazil
2a530712cf add os-prober parser 2022-11-07 13:23:55 -08:00
Kelly Brazil
fd22c7dc3a add git-ls-remote parser 2022-11-07 13:02:55 -08:00
Kelly Brazil
b884f6aacc doc update 2022-11-07 10:44:37 -08:00
Kelly Brazil
ce680d4082 add cidr-style freebsd ipv4 support and freebsd options 2022-11-07 10:40:07 -08:00
Kelly Brazil
644d3f350d add more bsd tests 2022-11-06 12:12:07 -08:00
Kelly Brazil
0144863d33 new ifconfig parser with additional fields. tests passing 2022-11-06 12:04:34 -08:00
Kelly Brazil
a6b56519a2 add more bsd fields to ifconfig 2022-11-05 18:47:44 -07:00
Kelly Brazil
0a71caf9cd formatting for regexes 2022-11-05 17:12:50 -07:00
Kelly Brazil
35e74328c4 tests passing for ifconfig 2022-11-05 16:36:31 -07:00
Kelly Brazil
e46ac0ff7e initial commit of new ifconfig parser 2022-11-05 12:13:01 -07:00
Kelly Brazil
17fe6c7691 semver tests and doc update 2022-11-04 16:03:39 -07:00
Kelly Brazil
01ca7a69c4 formatting 2022-11-04 15:24:34 -07:00
Kelly Brazil
6d04db6113 add semver parser 2022-11-04 15:17:47 -07:00
Kelly Brazil
7c899abb15 add support for multiple include paths 2022-11-04 14:42:04 -07:00
Kelly Brazil
89d4df2a05 document ifconfig limitations and recommend using ip 2022-11-04 09:25:17 -07:00
Kelly Brazil
71c8364f80 doc fix 2022-11-04 09:19:42 -07:00
Kelly Brazil
214cd6b9e0 Merge pull request #310 from villesinisalo/readme_arch
Readme: recommend plain Pacman on Arch
2022-11-03 15:34:19 +00:00
Ville Sinisalo
73c280de3a use plain Pacman on Arch 2022-11-03 11:29:06 +02:00
Kelly Brazil
23e1dd3e35 use dict constructor for xmltodict to suppress !!omap comments in YAML output 2022-11-02 12:00:45 -07:00
Kelly Brazil
2b060aae0d clean up raw/processed logic 2022-11-01 19:53:44 -07:00
Kelly Brazil
186ad73651 add raw option to xml parser for _ attribute prefix 2022-11-01 18:09:05 -07:00
Kelly Brazil
de7a010f62 update test templates 2022-11-01 17:01:21 -07:00
Kelly Brazil
ac1bcd2918 doc update 2022-11-01 15:28:50 -07:00
Kelly Brazil
a2e6243282 doc update and additional tests 2022-11-01 13:50:01 -07:00
Kelly Brazil
01f92ced81 add docs and tests for findmnt 2022-11-01 13:15:31 -07:00
Kelly Brazil
b493bcf4fa update type annotations 2022-10-31 17:37:01 -07:00
Kelly Brazil
f6ee30be20 formatting 2022-10-31 17:30:51 -07:00
Kelly Brazil
50da124ea7 initial findmnt parser 2022-10-31 17:22:56 -07:00
Kelly Brazil
5e22f9e2bd formatting 2022-10-31 10:29:43 -07:00
Kelly Brazil
a384eb4c15 add sshd_conf tests 2022-10-31 09:32:58 -07:00
Kelly Brazil
dc4620eeb2 doc update 2022-10-31 09:22:39 -07:00
Kelly Brazil
d7cfa38eee ignore Match blocks 2022-10-28 16:36:52 -07:00
Kelly Brazil
a27110ebe5 formatting 2022-10-28 15:25:55 -07:00
Kelly Brazil
f5988527fb add sshd_conf parser 2022-10-28 15:15:02 -07:00
Kelly Brazil
c405309742 allow debug of exceptions 2022-10-28 15:14:53 -07:00
Kelly Brazil
747d12224f allow parser_info and get_help to use module objects as input 2022-10-28 10:36:54 -07:00
Kelly Brazil
2b621ab68e use exceptions instead of signal handlers to catch piperror and sigint 2022-10-28 10:11:19 -07:00
Kelly Brazil
8689865d31 fix exit on interrupt exit code. also add message to stderr 2022-10-27 11:23:43 -07:00
Kelly Brazil
358324533d doc update 2022-10-26 15:39:32 -07:00
Kelly Brazil
bc5821e69f force ci tests 2022-10-26 15:36:22 -07:00
Kelly Brazil
d5b478c968 bump checkout and setup-python versions 2022-10-26 15:35:41 -07:00
Kelly Brazil
368eba1826 bump checkout and setup-python versions 2022-10-26 15:34:46 -07:00
Kelly Brazil
6cffb449f4 Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2022-10-26 15:23:35 -07:00
Kelly Brazil
d79d9c7f13 simplify return 2022-10-26 15:21:37 -07:00
Kelly Brazil
179822b994 add python 3.11 2022-10-26 15:18:33 -07:00
Kelly Brazil
ba369a0b73 add python 3.11 2022-10-26 15:18:04 -07:00
Kelly Brazil
6a5251f0ef doc update 2022-10-25 15:50:45 -07:00
Kelly Brazil
004fd74748 add type annotations 2022-10-25 15:21:42 -07:00
Kelly Brazil
e8d6d4c080 relax input_type_check to allow object argument 2022-10-25 15:21:26 -07:00
Kelly Brazil
8644f70db4 fix typos 2022-10-25 13:46:22 -07:00
Kelly Brazil
72f233b186 version bump 2022-10-25 11:53:08 -07:00
Kelly Brazil
fc85950a73 doc update 2022-10-25 11:49:02 -07:00
Kelly Brazil
fd5cbbb4d5 add csv utf-8 bom tests 2022-10-25 11:46:31 -07:00
Kelly Brazil
888b6bd6d5 fix for UTF-8 csv files with leading BOM bytes 2022-10-25 11:18:22 -07:00
Kelly Brazil
81ea83064c Merge pull request #306 from kellyjonbrazil/dev
Dev v1.22.1
2022-10-24 16:30:36 +00:00
Kelly Brazil
45859b01e5 doc update 2022-10-24 09:17:09 -07:00
Kelly Brazil
5b8f166169 doc update 2022-10-24 09:15:58 -07:00
Kelly Brazil
7e045ba7b0 doc update 2022-10-24 09:14:01 -07:00
Kelly Brazil
6247975ee6 update jc-web link to render 2022-10-23 13:20:50 -07:00
Kelly Brazil
297451230c lspci docs and tests 2022-10-23 09:15:23 -07:00
Kelly Brazil
754d555768 doc update 2022-10-21 13:09:13 -07:00
Kelly Brazil
b61a91f82d add pci-ids and udevadm tests 2022-10-21 12:57:28 -07:00
Kelly Brazil
1ac7a724bd integer conversions 2022-10-21 12:45:19 -07:00
Kelly Brazil
2fcf46505c add schema, typing, and doc update 2022-10-21 12:44:57 -07:00
Kelly Brazil
fdec4f08c0 add schema docs for pci-ids 2022-10-21 11:50:06 -07:00
Kelly Brazil
076c197385 more explicit type annotations 2022-10-21 10:56:10 -07:00
Kelly Brazil
3432e830f2 doc update 2022-10-19 13:46:32 -07:00
Kelly Brazil
14a237749c type annotation cleanup 2022-10-19 13:32:16 -07:00
Kelly Brazil
1559c4751e type annotate decorator function 2022-10-19 12:02:12 -07:00
Kelly Brazil
af7c4ce8ec doc update 2022-10-19 08:33:09 -07:00
Kelly Brazil
5763ce6160 Don't get too fancy with dict type annotations 2022-10-19 08:30:09 -07:00
Kelly Brazil
d7ca6caae8 use jc_types 2022-10-18 15:46:29 -07:00
Kelly Brazil
2c4f232aaa use jc_types 2022-10-18 15:45:29 -07:00
Kelly Brazil
bddfa71fa6 use object for typing since these functions accept other types 2022-10-18 15:44:53 -07:00
Kelly Brazil
f537ab058b use Tuple for <3.9 compatibility 2022-10-18 11:27:12 -07:00
Kelly Brazil
1b44b5b05a use typing Tuple for <3.9 compatibility 2022-10-18 11:24:55 -07:00
Kelly Brazil
f6e971c652 fix metadata return type 2022-10-18 11:04:08 -07:00
Kelly Brazil
dfa7a71f53 move custom types to jc_types 2022-10-18 11:01:59 -07:00
Kelly Brazil
3639e02843 doc update 2022-10-18 09:37:10 -07:00
Kelly Brazil
27b6e79c8a ignore mocking typing errors 2022-10-18 09:36:17 -07:00
Kelly Brazil
f370151b54 make iso_datetime deprecated only. no need to make hidden. 2022-10-18 09:35:59 -07:00
Kelly Brazil
597a8f468e normalize show_hidden and show_deprecated to be False by default 2022-10-18 09:35:24 -07:00
Kelly Brazil
8bd7a00410 add py.typed to package 2022-10-18 09:14:43 -07:00
Kelly Brazil
4867052972 fix AboutJCType 2022-10-15 18:27:55 -07:00
Kelly Brazil
688c3a34f6 define CustomColorType 2022-10-15 18:21:53 -07:00
Kelly Brazil
e357b27433 more granular type annotations 2022-10-15 17:53:02 -07:00
Kelly Brazil
dd70bf92f3 doc update 2022-10-15 14:43:45 -07:00
Kelly Brazil
0a97523928 doc update 2022-10-15 14:36:35 -07:00
Kelly Brazil
f67bd02283 More granular type annotations 2022-10-15 14:34:09 -07:00
Kelly Brazil
ef1055a9b6 more granular type annotations 2022-10-15 14:06:38 -07:00
Kelly Brazil
cd970b5871 TypedDict fixup for older python versions 2022-10-15 13:53:56 -07:00
Kelly Brazil
11b0863a65 Use TypedDict for more granular typing 2022-10-15 13:44:44 -07:00
Kelly Brazil
5b8cb497de add more type annotations 2022-10-14 17:28:34 -07:00
Kelly Brazil
38e2addbb6 simplify type annotation for MetadataType 2022-10-14 17:23:38 -07:00
Kelly Brazil
58158ce8b1 add type annotations 2022-10-14 17:12:58 -07:00
Kelly Brazil
5ca281f02e add type annotations 2022-10-14 15:54:26 -07:00
Kelly Brazil
ac39ce6b98 formatting 2022-10-14 14:07:05 -07:00
Kelly Brazil
38fb0a6828 allow parser module as parse() argument 2022-10-14 14:05:16 -07:00
Kelly Brazil
38c41cfaf4 formatting 2022-10-14 13:49:10 -07:00
Kelly Brazil
95ba628ac3 add more type annotations 2022-10-14 13:38:05 -07:00
Kelly Brazil
a53f2ecbaf split slot info 2022-10-12 09:07:17 -07:00
Kelly Brazil
aa1ff55bbe lower-case key names 2022-10-12 08:48:42 -07:00
Kelly Brazil
097d013447 remove bail if a, h, or v in magic_options to keep from confusing behavior 2022-10-11 17:18:55 -07:00
Kelly Brazil
3916623c46 remove multiple ands in conditional 2022-10-11 16:22:10 -07:00
Kelly Brazil
42c50c5fa1 remove unneeded fields 2022-10-11 13:44:28 -07:00
Kelly Brazil
ea515bbecc add show_hidden and show_deprecated tests 2022-10-11 12:19:11 -07:00
Kelly Brazil
9f8006060b deprecated parser support in lib 2022-10-10 16:34:32 -07:00
Kelly Brazil
6cd51c4426 add ip_split field 2022-10-10 12:21:02 -07:00
Kelly Brazil
b1e96bb50c add ip_split field 2022-10-10 12:19:39 -07:00
Kelly Brazil
50d3bda3b7 prefix ids with underscores for easier querying with jq, etc. 2022-10-10 11:37:33 -07:00
Kelly Brazil
3dfa4a1bbc rename iso-datetime to datetime-iso 2022-10-09 11:05:32 -07:00
Kelly Brazil
d1922acfc8 add datetime_iso tests 2022-10-09 11:03:31 -07:00
Kelly Brazil
3947e424e7 rename iso-datetime parser to datetime-iso 2022-10-09 11:00:02 -07:00
Kelly Brazil
25e202a09e doc update 2022-10-08 09:04:21 -07:00
Kelly Brazil
8eab3c1590 fixes for cli refactor 2022-10-08 09:04:04 -07:00
Kelly Brazil
4f294aa0ef add pci_ids parser 2022-10-07 16:36:46 -07:00
Kelly Brazil
81aa09a2e2 initial lspci parser 2022-10-07 13:06:20 -07:00
Kelly Brazil
10fc8cb48d add udevadm parser 2022-10-07 11:28:56 -07:00
Kelly Brazil
186f0708cc doc update 2022-10-07 09:34:42 -07:00
Kelly Brazil
622b3ff9ed add __slots__ to timestamp class 2022-10-06 09:05:36 -07:00
Kelly Brazil
c06963c3d6 doc update 2022-10-04 15:16:35 -07:00
Kelly Brazil
9009313748 move error codes from attribute to global constant 2022-10-04 15:04:00 -07:00
Kelly Brazil
d55a8c3079 clean up exit methods 2022-10-04 14:52:51 -07:00
Kelly Brazil
fee6a61f19 Merge pull request #299 from kellyjonbrazil/cli-refactor
Cli refactor
2022-10-04 21:18:58 +00:00
Kelly Brazil
6f1ef09d2a formatting 2022-10-04 14:13:48 -07:00
Kelly Brazil
cf6c13e605 remove old cli module 2022-10-04 14:07:02 -07:00
Kelly Brazil
028f55910a fix for rare instances when the output is a list of lists (yaml | yaml -> json) 2022-10-04 12:14:32 -07:00
Kelly Brazil
d7684d39a8 set magic_run_command_str in magic_parser 2022-10-04 11:48:36 -07:00
Kelly Brazil
f652ccd4b1 fix tests for env_colors 2022-10-04 11:39:50 -07:00
Kelly Brazil
6be92498bc remove self.env_colors attribute 2022-10-04 11:32:18 -07:00
Kelly Brazil
677e04ab7d cleanup 2022-10-04 11:15:37 -07:00
Kelly Brazil
46fdc457fc fix exit codes 2022-10-04 10:10:59 -07:00
Kelly Brazil
0306b6b73b simplify file open method 2022-10-04 09:38:46 -07:00
Kelly Brazil
c881653d55 simplify the run() method 2022-10-04 09:26:40 -07:00
Kelly Brazil
7650d831e3 add slots 2022-10-03 18:03:06 -07:00
Kelly Brazil
e7a8cc3b8b fix unbuffer 2022-10-03 17:38:55 -07:00
Kelly Brazil
d173b2f237 fix magic parser for cases where standard parser is found 2022-10-03 15:04:18 -07:00
Kelly Brazil
49ba6ed0f2 formatting 2022-10-03 13:13:10 -07:00
Kelly Brazil
2792d05c7f fix magic parser and tests 2022-10-03 13:03:42 -07:00
Kelly Brazil
cacda0f3cc fix cli tests 2022-10-03 12:49:13 -07:00
Kelly Brazil
c420547ff8 simplify monochrome settings 2022-10-03 11:30:29 -07:00
Kelly Brazil
83d388613f cleanup 2022-10-03 08:58:09 -07:00
Kelly Brazil
094b059aea fix magic options 2022-10-02 19:30:50 -07:00
Kelly Brazil
e36a8c627b fix meta timestamp 2022-10-02 18:55:54 -07:00
Kelly Brazil
d341e91290 cleanup 2022-10-02 18:29:02 -07:00
Kelly Brazil
557afc95bd initial working 2022-10-02 18:20:14 -07:00
Kelly Brazil
cb9979ac94 refactor cli 2022-10-02 16:58:20 -07:00
Kelly Brazil
5486957141 version bump 2022-09-29 09:14:53 -07:00
Kelly Brazil
d49155df95 make regex patterns raw strings to reduce pytest warnings 2022-09-28 15:09:06 -07:00
Kelly Brazil
0dd4b5f620 parser version bump 2022-09-28 14:56:37 -07:00
Kelly Brazil
690603bfda fix proc-pid-stat parser for command names with spaces and newlines 2022-09-28 14:55:25 -07:00
444 changed files with 57292 additions and 2526 deletions

View File

@@ -13,11 +13,11 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
python-version: ["3.7", "3.8", "3.9", "3.10"]
os: [macos-latest, ubuntu-20.04, windows-latest]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: "Set up timezone to America/Los_Angeles"
uses: szenius/set-timezone@v1.0
with:
@@ -25,7 +25,7 @@ jobs:
timezoneMacos: "America/Los_Angeles"
timezoneWindows: "Pacific Standard Time"
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies

View File

@@ -1,5 +1,75 @@
jc changelog
20230111 v1.22.5
- Add TOML file parser
- Add INI with duplicate key support file parser
- Add AIX support for the `arp` command parser
- Add AIX support for the `mount` command parser
- Fix `lsusb` command parser when extra hub port status information is output
- Refactor `lsusb` command parser for more code reuse
- Fix INI file parser to include top-level values with no section header
- Fix INI file parser to not specially handle the [DEFAULT] section
- Fix INI file and Key/Value parsers to only remove one quotation mark from the
beginning and end of values.
- Update copyright dates
20221230 v1.22.4
- Add `iwconfig` command parser
- Add NeXTSTEP format support to the PLIST file parser
- Fix `proc` parser magic signature detection for `/proc/pid/stat` hacks
- Fix `x509-cert` parser for string serial numbers
- Add category tags to parser metadata: generic, standard, file, string, binary, command
- Add "list parsers by category" view to help
- Fix python 3.6-related issues
- Add python 3.6 to automated tests
20221216 v1.22.3
- Add Common Log Format and Combined Log Format file parser (standard and streaming)
- Add PostgreSQL password file parser
- Add openvpn-status.log file parser
- Add `cbt` command parser (Google Big Table)
- Enhance `ifconfig` parser with interface lane information on BSD
- Enhance `ifconfig` parser with additional IPv6 `scope_id` info for BSD
- Fix `ifconfig` parser to capture some IPv6 addresses missed on BSD
- Fix `git-log` and `git-log-s` parsers for failure on empty author name
- Update `os-prober` parser with split EFI partition fields
- Add ISO string attribute (`.iso`) to `jc.utils.timestamp()`
- Fix several documentation typos
20221107 v1.22.2
- add `sshd_conf` parser for `sshd` configuration files and `sshd -T` output
- add `findmnt` command parser
- add `git ls-remote` command parser
- add `os-prober` command parser
- add SemVer string parser
- enhance the `ifconfig` parser so it can output multiple IPv4 and IPv6 addresses
- enhance the `ifconfig` parser so it can output additional fields common on BSD
- enhance `xml` parser with optional `_` prefix for attributes instead of
`@` by using the `--raw` option. This can make it easier to filter the
JSON output in some tools.
- fix the `xml` parser to output a normal Dictionary instead of OrderdDict.
This cleans up YAML output. (No `!!omap` comments)
- fix `csv` and `csv-s` parsers for UTF-8 encoded CSV files with leading BOM bytes
- fix exit code to be non-zero on interrupt
- allow parser module objects to be used as arguments to `jc.get_help()` and `jc.parser_info()`
- catch unexpected exceptions in the CLI
- add error message on interrupt to STDERR
- add python 3.11 tests to github actions
20221024 v1.22.1
- add `udevadm` command parser
- add `lspci` command parser
- add `pci.ids` file parser
- fix `proc-pid-stat` parser for command names with spaces and newlines
- enhance `ip-address` parser to add `ip_split` field
- rename `iso-datetime` parser to `datetime-iso`. A deprecation warning will
display until `iso-datetime` is removed in a future version.
- refactor cli module
- optimize performance of calculated timestamps
- add more type annotations
- add support for deprecating parsers
- move jc-web demo site from heroku to render.com
20220926 v1.22.0
- Add /proc file parsers for linux. Support for the following files:
`/proc/buddyinfo`
@@ -547,7 +617,7 @@ jc changelog
20200211 v1.7.3
- Add alternative 'magic' syntax: e.g. `jc ls -al`
- Options can now be condensed (e.g. -prq is equivalant to -p -r -q)
- Options can now be condensed (e.g. -prq is equivalent to -p -r -q)
20200208 v1.7.2
- Include test fixtures in wheel and sdist

View File

@@ -1636,21 +1636,21 @@ cat example.ini | jc --ini -p
```
```json
{
"bitbucket.org": {
"ServeraLiveInterval": "45",
"DEFAULT": {
"ServerAliveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "yes",
"ForwardX11": "yes"
},
"bitbucket.org": {
"User": "hg"
},
"topsecret.server.com": {
"ServeraLiveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "no",
"Port": "50022"
"Port": "50022",
"ForwardX11": "no"
}
}
```
### iostat
```bash
@@ -1707,6 +1707,12 @@ echo 192.168.2.10/24 | jc --ip-address -p
"ip": "192.168.2.10",
"ip_compressed": "192.168.2.10",
"ip_exploded": "192.168.2.10",
"ip_split": [
"192",
"168",
"2",
"10"
],
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
@@ -1819,7 +1825,7 @@ iptables --line-numbers -v -L -t nat | jc --iptables -p # or: jc -p ip
```
### ISO Datetime string
```bash
echo "2022-07-20T14:52:45Z" | jc --iso-datetime -p
echo "2022-07-20T14:52:45Z" | jc --datetime-iso -p
```
```json
{

View File

@@ -1,2 +1,3 @@
include jc/py.typed
include man/jc.1
include CHANGELOG

View File

@@ -3,7 +3,7 @@
> Check out the `jc` Python [package documentation](https://github.com/kellyjonbrazil/jc/tree/master/docs) for developers
> Try the `jc` [web demo](https://jc-web-demo.herokuapp.com/)
> Try the `jc` [web demo](https://jc-web.onrender.com/)
> JC is [now available](https://galaxy.ansible.com/community/general) as an
Ansible filter plugin in the `community.general` collection. See this
@@ -114,7 +114,7 @@ pip3 install jc
| Debian/Ubuntu linux | `apt-get install jc` |
| Fedora linux | `dnf install jc` |
| openSUSE linux | `zypper install jc` |
| Archlinux Community Repository | `paru -S jc` or `aura -S jc` or `yay -S jc` |
| Arch linux | `pacman -S jc` |
| NixOS linux | `nix-env -iA nixpkgs.jc` or `nix-env -iA nixos.jc` |
| Guix System linux | `guix install jc` |
| Gentoo Linux | `emerge dev-python/jc` |
@@ -161,15 +161,19 @@ option.
| ` --asciitable` | ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable) |
| ` --asciitable-m` | multi-line ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m) |
| ` --blkid` | `blkid` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid) |
| ` --cbt` | `cbt` (Google Bigtable) command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cbt) |
| ` --cef` | CEF string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef) |
| ` --cef-s` | CEF string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef_s) |
| ` --chage` | `chage --list` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/chage) |
| ` --cksum` | `cksum` and `sum` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum) |
| ` --clf` | Common and Combined Log Format file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/clf) |
| ` --clf-s` | Common and Combined Log Format file streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/clf_s) |
| ` --crontab` | `crontab` command and file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab) |
| ` --crontab-u` | `crontab` file parser with user support | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u) |
| ` --csv` | CSV file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/csv) |
| ` --csv-s` | CSV file streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s) |
| ` --date` | `date` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/date) |
| ` --datetime-iso` | ISO 8601 Datetime string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/datetime_iso) |
| ` --df` | `df` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/df) |
| ` --dig` | `dig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dig) |
| ` --dir` | `dir` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dir) |
@@ -179,11 +183,13 @@ option.
| `--email-address` | Email Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/email_address) |
| ` --env` | `env` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/env) |
| ` --file` | `file` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/file) |
| ` --findmnt` | `findmnt` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/findmnt) |
| ` --finger` | `finger` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/finger) |
| ` --free` | `free` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/free) |
| ` --fstab` | `/etc/fstab` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/fstab) |
| ` --git-log` | `git log` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log) |
| ` --git-log-s` | `git log` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log_s) |
| `--git-ls-remote` | `git ls-remote` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_ls_remote) |
| ` --gpg` | `gpg --with-colons` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/gpg) |
| ` --group` | `/etc/group` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/group) |
| ` --gshadow` | `/etc/gshadow` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/gshadow) |
@@ -195,22 +201,24 @@ option.
| ` --id` | `id` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/id) |
| ` --ifconfig` | `ifconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig) |
| ` --ini` | INI file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ini) |
| ` --ini-dup` | INI with duplicate key file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ini_dup) |
| ` --iostat` | `iostat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat) |
| ` --iostat-s` | `iostat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s) |
| ` --ip-address` | IPv4 and IPv6 Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ip_address) |
| ` --iptables` | `iptables` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables) |
| ` --iso-datetime` | ISO 8601 Datetime string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iso_datetime) |
| ` --iw-scan` | `iw dev [device] scan` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan) |
| ` --iwconfig` | `iwconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iwconfig) |
| ` --jar-manifest` | Java MANIFEST.MF file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) |
| ` --jobs` | `jobs` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs) |
| ` --jwt` | JWT string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jwt) |
| ` --kv` | Key/Value file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/kv) |
| ` --kv` | Key/Value file and string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/kv) |
| ` --last` | `last` and `lastb` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/last) |
| ` --ls` | `ls` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls) |
| ` --ls-s` | `ls` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s) |
| ` --lsblk` | `lsblk` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk) |
| ` --lsmod` | `lsmod` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod) |
| ` --lsof` | `lsof` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof) |
| ` --lspci` | `lspci -mmv` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lspci) |
| ` --lsusb` | `lsusb` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb) |
| ` --m3u` | M3U and M3U8 file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/m3u) |
| ` --mdadm` | `mdadm` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mdadm) |
@@ -220,7 +228,11 @@ option.
| ` --netstat` | `netstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat) |
| ` --nmcli` | `nmcli` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli) |
| ` --ntpq` | `ntpq -p` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq) |
| ` --openvpn` | openvpn-status.log file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/openvpn) |
| ` --os-prober` | `os-prober` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/os_prober) |
| ` --passwd` | `/etc/passwd` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd) |
| ` --pci-ids` | `pci.ids` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pci_ids) |
| ` --pgpass` | PostgreSQL password file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pgpass) |
| ` --pidstat` | `pidstat -H` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat) |
| ` --pidstat-s` | `pidstat -H` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat_s) |
| ` --ping` | `ping` and `ping6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ping) |
@@ -235,9 +247,11 @@ option.
| ` --rpm-qi` | `rpm -qi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi) |
| ` --rsync` | `rsync` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync) |
| ` --rsync-s` | `rsync` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s) |
| ` --semver` | Semantic Version string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/semver) |
| ` --sfdisk` | `sfdisk` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sfdisk) |
| ` --shadow` | `/etc/shadow` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/shadow) |
| ` --ss` | `ss` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ss) |
| ` --sshd-conf` | sshd config file and `sshd -T` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sshd_conf) |
| ` --stat` | `stat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat) |
| ` --stat-s` | `stat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s) |
| ` --sysctl` | `sysctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl) |
@@ -253,10 +267,12 @@ option.
| ` --time` | `/usr/bin/time` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/time) |
| ` --timedatectl` | `timedatectl status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl) |
| ` --timestamp` | Unix Epoch Timestamp string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timestamp) |
| ` --toml` | TOML file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/toml) |
| ` --top` | `top -b` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top) |
| ` --top-s` | `top -b` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
| ` --tracepath` | `tracepath` and `tracepath6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
| ` --traceroute` | `traceroute` and `traceroute6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute) |
| ` --udevadm` | `udevadm info` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/udevadm) |
| ` --ufw` | `ufw status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw) |
| ` --ufw-appinfo` | `ufw app info [application]` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw_appinfo) |
| ` --uname` | `uname -a` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/uname) |
@@ -382,7 +398,7 @@ option.
### Streaming Parsers
Most parsers load all of the data from `STDIN`, parse it, then output the entire
JSON document serially. There are some streaming parsers (e.g. `ls-s` and
`ping-s`) that immediately start processing and outputing the data line-by-line
`ping-s`) that immediately start processing and outputting the data line-by-line
as [JSON Lines](https://jsonlines.org/) (aka [NDJSON](http://ndjson.org/)) while
it is being received from `STDIN`. This can significantly reduce the amount of
memory required to parse large amounts of command output (e.g. `ls -lR /`) and
@@ -742,37 +758,31 @@ ifconfig | jc -p --ifconfig # or: jc -p ifconfig
cat example.ini
```
```
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
foo = fiz
bar = buz
[bitbucket.org]
User = hg
[section1]
fruit = apple
color = blue
[topsecret.server.com]
Port = 50022
ForwardX11 = no
[section2]
fruit = pear
color = green
```
```bash
cat example.ini | jc -p --ini
```
```json
{
"bitbucket.org": {
"ServeraLiveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "yes",
"User": "hg"
"foo": "fiz",
"bar": "buz",
"section1": {
"fruit": "apple",
"color": "blue"
},
"topsecret.server.com": {
"ServeraLiveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "no",
"Port": "50022"
"section2": {
"fruit": "pear",
"color": "green"
}
}
```
@@ -1228,4 +1238,4 @@ cat istio.yaml | jc -p --yaml
]
```
© 2019-2022 Kelly Brazil
© 2019-2023 Kelly Brazil

View File

@@ -3,8 +3,8 @@ _jc()
local cur prev words cword jc_commands jc_parsers jc_options \
jc_about_options jc_about_mod_options jc_help_options jc_special_options
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cef --cef-s --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --ip-address --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_commands=(acpi airport arp blkid cbt chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw iwconfig jobs last lastb ls lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cbt --cef --cef-s --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --ss --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_about_options=(--about -a)
jc_about_mod_options=(--pretty -p --yaml-out -y --monochrome -m --force-color -C)

View File

@@ -9,12 +9,13 @@ _jc() {
jc_help_options jc_help_options_describe \
jc_special_options jc_special_options_describe
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_commands=(acpi airport arp blkid cbt chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw iwconfig jobs last lastb ls lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_commands_describe=(
'acpi:run "acpi" command with magic syntax.'
'airport:run "airport" command with magic syntax.'
'arp:run "arp" command with magic syntax.'
'blkid:run "blkid" command with magic syntax.'
'cbt:run "cbt" command with magic syntax.'
'chage:run "chage" command with magic syntax.'
'cksum:run "cksum" command with magic syntax.'
'crontab:run "crontab" command with magic syntax.'
@@ -26,6 +27,7 @@ _jc() {
'du:run "du" command with magic syntax.'
'env:run "env" command with magic syntax.'
'file:run "file" command with magic syntax.'
'findmnt:run "findmnt" command with magic syntax.'
'finger:run "finger" command with magic syntax.'
'free:run "free" command with magic syntax.'
'git:run "git" command with magic syntax.'
@@ -36,6 +38,7 @@ _jc() {
'iostat:run "iostat" command with magic syntax.'
'iptables:run "iptables" command with magic syntax.'
'iw:run "iw" command with magic syntax.'
'iwconfig:run "iwconfig" command with magic syntax.'
'jobs:run "jobs" command with magic syntax.'
'last:run "last" command with magic syntax.'
'lastb:run "lastb" command with magic syntax.'
@@ -43,6 +46,7 @@ _jc() {
'lsblk:run "lsblk" command with magic syntax.'
'lsmod:run "lsmod" command with magic syntax.'
'lsof:run "lsof" command with magic syntax.'
'lspci:run "lspci" command with magic syntax.'
'lsusb:run "lsusb" command with magic syntax.'
'md5:run "md5" command with magic syntax.'
'md5sum:run "md5sum" command with magic syntax.'
@@ -52,6 +56,7 @@ _jc() {
'netstat:run "netstat" command with magic syntax.'
'nmcli:run "nmcli" command with magic syntax.'
'ntpq:run "ntpq" command with magic syntax.'
'os-prober:run "os-prober" command with magic syntax.'
'pidstat:run "pidstat" command with magic syntax.'
'ping:run "ping" command with magic syntax.'
'ping6:run "ping6" command with magic syntax.'
@@ -71,6 +76,7 @@ _jc() {
'sha512sum:run "sha512sum" command with magic syntax.'
'shasum:run "shasum" command with magic syntax.'
'ss:run "ss" command with magic syntax.'
'sshd:run "sshd" command with magic syntax.'
'stat:run "stat" command with magic syntax.'
'sum:run "sum" command with magic syntax.'
'sysctl:run "sysctl" command with magic syntax.'
@@ -82,6 +88,7 @@ _jc() {
'tracepath6:run "tracepath6" command with magic syntax.'
'traceroute:run "traceroute" command with magic syntax.'
'traceroute6:run "traceroute6" command with magic syntax.'
'udevadm:run "udevadm" command with magic syntax.'
'ufw:run "ufw" command with magic syntax.'
'uname:run "uname" command with magic syntax.'
'update-alternatives:run "update-alternatives" command with magic syntax.'
@@ -95,7 +102,7 @@ _jc() {
'xrandr:run "xrandr" command with magic syntax.'
'zipinfo:run "zipinfo" command with magic syntax.'
)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cef --cef-s --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --ip-address --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cbt --cef --cef-s --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --ss --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_parsers_describe=(
'--acpi:`acpi` command parser'
'--airport:`airport -I` command parser'
@@ -104,15 +111,19 @@ _jc() {
'--asciitable:ASCII and Unicode table parser'
'--asciitable-m:multi-line ASCII and Unicode table parser'
'--blkid:`blkid` command parser'
'--cbt:`cbt` (Google Bigtable) command parser'
'--cef:CEF string parser'
'--cef-s:CEF string streaming parser'
'--chage:`chage --list` command parser'
'--cksum:`cksum` and `sum` command parser'
'--clf:Common and Combined Log Format file parser'
'--clf-s:Common and Combined Log Format file streaming parser'
'--crontab:`crontab` command and file parser'
'--crontab-u:`crontab` file parser with user support'
'--csv:CSV file parser'
'--csv-s:CSV file streaming parser'
'--date:`date` command parser'
'--datetime-iso:ISO 8601 Datetime string parser'
'--df:`df` command parser'
'--dig:`dig` command parser'
'--dir:`dir` command parser'
@@ -122,11 +133,13 @@ _jc() {
'--email-address:Email Address string parser'
'--env:`env` command parser'
'--file:`file` command parser'
'--findmnt:`findmnt` command parser'
'--finger:`finger` command parser'
'--free:`free` command parser'
'--fstab:`/etc/fstab` file parser'
'--git-log:`git log` command parser'
'--git-log-s:`git log` command streaming parser'
'--git-ls-remote:`git ls-remote` command parser'
'--gpg:`gpg --with-colons` command parser'
'--group:`/etc/group` file parser'
'--gshadow:`/etc/gshadow` file parser'
@@ -138,22 +151,24 @@ _jc() {
'--id:`id` command parser'
'--ifconfig:`ifconfig` command parser'
'--ini:INI file parser'
'--ini-dup:INI with duplicate key file parser'
'--iostat:`iostat` command parser'
'--iostat-s:`iostat` command streaming parser'
'--ip-address:IPv4 and IPv6 Address string parser'
'--iptables:`iptables` command parser'
'--iso-datetime:ISO 8601 Datetime string parser'
'--iw-scan:`iw dev [device] scan` command parser'
'--iwconfig:`iwconfig` command parser'
'--jar-manifest:Java MANIFEST.MF file parser'
'--jobs:`jobs` command parser'
'--jwt:JWT string parser'
'--kv:Key/Value file parser'
'--kv:Key/Value file and string parser'
'--last:`last` and `lastb` command parser'
'--ls:`ls` command parser'
'--ls-s:`ls` command streaming parser'
'--lsblk:`lsblk` command parser'
'--lsmod:`lsmod` command parser'
'--lsof:`lsof` command parser'
'--lspci:`lspci -mmv` command parser'
'--lsusb:`lsusb` command parser'
'--m3u:M3U and M3U8 file parser'
'--mdadm:`mdadm` command parser'
@@ -163,7 +178,11 @@ _jc() {
'--netstat:`netstat` command parser'
'--nmcli:`nmcli` command parser'
'--ntpq:`ntpq -p` command parser'
'--openvpn:openvpn-status.log file parser'
'--os-prober:`os-prober` command parser'
'--passwd:`/etc/passwd` file parser'
'--pci-ids:`pci.ids` file parser'
'--pgpass:PostgreSQL password file parser'
'--pidstat:`pidstat -H` command parser'
'--pidstat-s:`pidstat -H` command streaming parser'
'--ping:`ping` and `ping6` command parser'
@@ -227,9 +246,11 @@ _jc() {
'--rpm-qi:`rpm -qi` command parser'
'--rsync:`rsync` command parser'
'--rsync-s:`rsync` command streaming parser'
'--semver:Semantic Version string parser'
'--sfdisk:`sfdisk` command parser'
'--shadow:`/etc/shadow` file parser'
'--ss:`ss` command parser'
'--sshd-conf:sshd config file and `sshd -T` command parser'
'--stat:`stat` command parser'
'--stat-s:`stat` command streaming parser'
'--sysctl:`sysctl` command parser'
@@ -245,10 +266,12 @@ _jc() {
'--time:`/usr/bin/time` command parser'
'--timedatectl:`timedatectl status` command parser'
'--timestamp:Unix Epoch Timestamp string parser'
'--toml:TOML file parser'
'--top:`top -b` command parser'
'--top-s:`top -b` command streaming parser'
'--tracepath:`tracepath` and `tracepath6` command parser'
'--traceroute:`traceroute` and `traceroute6` command parser'
'--udevadm:`udevadm info` command parser'
'--ufw:`ufw status` command parser'
'--ufw-appinfo:`ufw app info [application]` command parser'
'--uname:`uname -a` command parser'
@@ -270,8 +293,8 @@ _jc() {
)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_options_describe=(
'--force-color:force color output even when using pipes (overrides -m)'
'-C:force color output even when using pipes (overrides -m)'
'--force-color:force color output (overrides -m)'
'-C:force color output (overrides -m)'
'--debug:debug (double for verbose debug)'
'-d:debug (double for verbose debug)'
'--monochrome:monochrome output'
@@ -302,8 +325,8 @@ _jc() {
'-y:YAML output'
'--monochrome:monochrome output'
'-m:monochrome output'
'--force-color:force color output even when using pipes (overrides -m)'
'-C:force color output even when using pipes (overrides -m)'
'--force-color:force color output (overrides -m)'
'-C:force color output (overrides -m)'
)
jc_help_options=(--help -h)
jc_help_options_describe=(

View File

@@ -21,15 +21,18 @@ jc - JSON Convert lib module
### parse
```python
def parse(parser_mod_name: str,
data: Union[str, bytes, Iterable[str]],
quiet: bool = False,
raw: bool = False,
ignore_exceptions: bool = None,
**kwargs) -> Union[Dict, List[Dict], Iterator[Dict]]
def parse(
parser_mod_name: Union[str, ModuleType],
data: Union[str, bytes, Iterable[str]],
quiet: bool = False,
raw: bool = False,
ignore_exceptions: bool = None,
**kwargs
) -> Union[JSONDictType, List[JSONDictType], Iterator[JSONDictType]]
```
Parse the string data using the supplied parser module.
Parse the data (string or bytes) using the supplied parser (string or
module object).
This function provides a high-level API to simplify parser use. This
function will call built-in parsers and custom plugin parsers.
@@ -53,6 +56,14 @@ Example (streaming parsers):
To get a list of available parser module names, use `parser_mod_list()`.
Alternatively, a parser module object can be supplied:
>>> import jc
>>> import jc.parsers.date as jc_date
>>> date_obj = jc.parse(jc_date, 'Tue Jan 18 10:23:07 PST 2022')
>>> print(f'The year is: {date_obj["year"]}')
The year is: 2022
You can also use the lower-level parser modules directly:
>>> import jc.parsers.date
@@ -73,11 +84,14 @@ parsers without this API:
Parameters:
parser_mod_name: (string) name of the parser module. This
function will accept module_name,
parser_mod_name: (string or name of the parser module. This
Module) function will accept module_name,
cli-name, and --argument-name
variants of the module name.
A Module object can also be passed
directly or via _get_parser()
data: (string or data to parse (string or bytes for
bytes or standard parsers, iterable of
iterable) strings for streaming parsers)
@@ -99,7 +113,8 @@ Returns:
### parser\_mod\_list
```python
def parser_mod_list() -> List[str]
def parser_mod_list(show_hidden: bool = False,
show_deprecated: bool = False) -> List[str]
```
Returns a list of all available parser module names.
@@ -109,7 +124,8 @@ Returns a list of all available parser module names.
### plugin\_parser\_mod\_list
```python
def plugin_parser_mod_list() -> List[str]
def plugin_parser_mod_list(show_hidden: bool = False,
show_deprecated: bool = False) -> List[str]
```
Returns a list of plugin parser module names. This function is a
@@ -120,7 +136,8 @@ subset of `parser_mod_list()`.
### standard\_parser\_mod\_list
```python
def standard_parser_mod_list() -> List[str]
def standard_parser_mod_list(show_hidden: bool = False,
show_deprecated: bool = False) -> List[str]
```
Returns a list of standard parser module names. This function is a
@@ -132,7 +149,8 @@ parsers.
### streaming\_parser\_mod\_list
```python
def streaming_parser_mod_list() -> List[str]
def streaming_parser_mod_list(show_hidden: bool = False,
show_deprecated: bool = False) -> List[str]
```
Returns a list of streaming parser module names. This function is a
@@ -143,17 +161,19 @@ subset of `parser_mod_list()`.
### parser\_info
```python
def parser_info(parser_mod_name: str, documentation: bool = False) -> Dict
def parser_info(parser_mod_name: Union[str, ModuleType],
documentation: bool = False) -> ParserInfoType
```
Returns a dictionary that includes the parser module metadata.
Parameters:
parser_mod_name: (string) name of the parser module. This
function will accept module_name,
parser_mod_name: (string or name of the parser module. This
Module) function will accept module_name,
cli-name, and --argument-name
variants of the module name.
variants of the module name as well
as a parser module object.
documentation: (boolean) include parser docstring if True
@@ -163,28 +183,33 @@ Parameters:
```python
def all_parser_info(documentation: bool = False,
show_hidden: bool = False) -> List[Dict]
show_hidden: bool = False,
show_deprecated: bool = False) -> List[ParserInfoType]
```
Returns a list of dictionaries that includes metadata for all parser
modules.
modules. By default only non-hidden, non-deprecated parsers are
returned.
Parameters:
documentation: (boolean) include parser docstrings if True
show_hidden: (boolean) also show parsers marked as hidden
in their info metadata.
show_deprecated: (boolean) also show parsers marked as
deprecated in their info metadata.
<a id="jc.lib.get_help"></a>
### get\_help
```python
def get_help(parser_mod_name: str) -> None
def get_help(parser_mod_name: Union[str, ModuleType]) -> None
```
Show help screen for the selected parser.
This function will accept **module_name**, **cli-name**, and
**--argument-name** variants of the module name string.
**--argument-name** variants of the module name string as well as a
parser module object.

View File

@@ -140,4 +140,4 @@ Returns:
### Parser Information
Compatibility: linux, aix, freebsd, darwin
Version 1.11 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.12 by Kelly Brazil (kellyjonbrazil@gmail.com)

125
docs/parsers/cbt.md Normal file
View File

@@ -0,0 +1,125 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.cbt"></a>
# jc.parsers.cbt
jc - JSON Convert `cbt` command output parser (Google Bigtable)
Parses the human-, but not machine-, friendly output of the cbt command (for
Google's Bigtable).
No effort is made to convert the data types of the values in the cells.
The `timestamp_epoch` calculated timestamp field is naive. (i.e. based on
the local time of the system the parser is run on)
The `timestamp_epoch_utc` calculated timestamp field is timezone-aware and
is only available if the timestamp has a UTC timezone.
The `timestamp_iso` calculated timestamp field will only include UTC
timezone information if the timestamp has a UTC timezone.
Raw output contains all cells for each column (including timestamps), while
the normal output contains only the latest value for each column.
Usage (cli):
$ cbt | jc --cbt
or
$ jc cbt
Usage (module):
import jc
result = jc.parse('cbt', cbt_command_output)
Schema:
[
{
"key": string,
"cells": {
<string>: { # column family
<string>: string # column: value
}
}
}
]
Schema (raw):
[
{
"key": string,
"cells": [
{
"column_family": string,
"column": string,
"value": string,
"timestamp_iso": string,
"timestamp_epoch": integer,
"timestamp_epoch_utc": integer
}
]
}
]
Examples:
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p
[
{
"key": "foo",
"cells": {
"foo": {
"bar": "baz"
}
}
}
]
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p -r
[
{
"key": "foo",
"cells": [
{
"column_family": "foo",
"column": "bar",
"value": "baz1",
"timestamp_iso": "1970-01-01T01:00:00",
"timestamp_epoch": 32400,
"timestamp_epoch_utc": null
}
]
}
]
<a id="jc.parsers.cbt.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Andreas Weiden (andreas.weiden@gmail.com)

199
docs/parsers/clf.md Normal file
View File

@@ -0,0 +1,199 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.clf"></a>
# jc.parsers.clf
jc - JSON Convert Common Log Format file parser
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf
Usage (module):
import jc
result = jc.parse('clf', common_log_file_output)
Schema:
Empty strings and `-` values are converted to `null`/`None`.
[
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
]
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf -p
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": 10,
"month": "Oct",
"year": 2000,
"hour": 13,
"minute": 55,
"second": 36,
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": 200,
"bytes": 2326,
"referer": null,
"user_agent": null,
"extra": null,
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0",
"epoch": 971211336,
"epoch_utc": null
},
{
"host": "1.1.1.2",
"ident": null,
"authuser": null,
"date": "11/Nov/2016:03:04:55 +0100",
"day": 11,
"month": "Nov",
"year": 2016,
"hour": 3,
"minute": 4,
"second": 55,
"tz": "+0100",
"request": "GET /",
"status": 200,
"bytes": 83,
"referer": null,
"user_agent": null,
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null,
"epoch": 1478862295,
"epoch_utc": null
},
...
]
$ cat file.log | jc --clf -p -r
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": "10",
"month": "Oct",
"year": "2000",
"hour": "13",
"minute": "55",
"second": "36",
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": "200",
"bytes": "2326",
"referer": null,
"user_agent": null,
"extra": "",
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0"
},
{
"host": "1.1.1.2",
"ident": "-",
"authuser": "-",
"date": "11/Nov/2016:03:04:55 +0100",
"day": "11",
"month": "Nov",
"year": "2016",
"hour": "03",
"minute": "04",
"second": "55",
"tz": "+0100",
"request": "GET /",
"status": "200",
"bytes": "83",
"referer": "-",
"user_agent": "-",
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null
},
...
]
<a id="jc.parsers.clf.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

117
docs/parsers/clf_s.md Normal file
View File

@@ -0,0 +1,117 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.clf_s"></a>
# jc.parsers.clf\_s
jc - JSON Convert Common Log Format file streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf-s
Usage (module):
import jc
result = jc.parse('clf_s', common_log_file_output.splitlines())
for item in result:
# do something
Schema:
Empty strings and `-` values are converted to `null`/`None`.
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf-s
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":null,"authuser":null,"date":"11/Nov/2016...}
...
$ cat file.log | jc --clf-s -r
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":"-","authuser":"-","date":"11/Nov/2016:0...}
...
<a id="jc.parsers.clf_s.parse"></a>
### parse
```python
@add_jc_meta
def parse(data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False) -> StreamingOutputType
```
Main text parsing generator function. Returns an iterable object.
Parameters:
data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Returns:
Iterable of Dictionaries
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -82,7 +82,9 @@ Examples:
### parse
```python
def parse(data, raw=False, quiet=False)
def parse(data: Union[str, bytes],
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
@@ -100,4 +102,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)

View File

@@ -86,4 +86,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -0,0 +1,91 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.datetime_iso"></a>
# jc.parsers.datetime\_iso
jc - JSON Convert ISO 8601 Datetime string parser
This parser supports standard ISO 8601 strings that include both date and
time. If no timezone or offset information is available in the string, then
UTC timezone is used.
Usage (cli):
$ echo "2022-07-20T14:52:45Z" | jc --iso-datetime
Usage (module):
import jc
result = jc.parse('iso_datetime', iso_8601_string)
Schema:
{
"year": integer,
"month": string,
"month_num": integer,
"day": integer,
"weekday": string,
"weekday_num": integer,
"hour": integer,
"hour_24": integer,
"minute": integer,
"second": integer,
"microsecond": integer,
"period": string,
"utc_offset": string,
"day_of_year": integer,
"week_of_year": integer,
"iso": string,
"timestamp": integer # [0]
}
[0] timezone aware UNIX timestamp expressed in UTC
Examples:
$ echo "2022-07-20T14:52:45Z" | jc --iso-datetime -p
{
"year": 2022,
"month": "Jul",
"month_num": 7,
"day": 20,
"weekday": "Wed",
"weekday_num": 3,
"hour": 2,
"hour_24": 14,
"minute": 52,
"second": 45,
"microsecond": 0,
"period": "PM",
"utc_offset": "+0000",
"day_of_year": 201,
"week_of_year": 29,
"iso": "2022-07-20T14:52:45+00:00",
"timestamp": 1658328765
}
<a id="jc.parsers.datetime_iso.parse"></a>
### parse
```python
def parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, aix, freebsd, darwin, win32, cygwin
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -106,7 +106,7 @@ Schema:
]
[0] naive timestamp if "when" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:

View File

@@ -5,6 +5,10 @@
jc - JSON Convert `du` command output parser
The `du -h` option is not supported with the default output. If you
would like to use `du -h` or other options that change the output, be sure
to use `jc --raw` (cli) or `raw=True` (module).
Usage (cli):
$ du | jc --du

117
docs/parsers/findmnt.md Normal file
View File

@@ -0,0 +1,117 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.findmnt"></a>
# jc.parsers.findmnt
jc - JSON Convert `findmnt` command output parser
Supports `-a`, `-l`, or no `findmnt` options.
> Note: Newer versions of `findmnt` have a JSON output option.
Usage (cli):
$ findmnt | jc --findmnt
or
$ jc findmnt
Usage (module):
import jc
result = jc.parse('findmnt', findmnt_command_output)
Schema:
[
{
"target": string,
"source": string,
"fstype": string,
"options": [
string
],
"kv_options": {
"<key_name>": string
}
]
Examples:
$ findmnt | jc --findmnt -p
[
{
"target": "/",
"source": "/dev/mapper/centos-root",
"fstype": "xfs",
"options": [
"rw",
"relatime",
"seclabel",
"attr2",
"inode64",
"noquota"
]
},
{
"target": "/sys/fs/cgroup",
"source": "tmpfs",
"fstype": "tmpfs",
"options": [
"ro",
"nosuid",
"nodev",
"noexec",
"seclabel"
],
"kv_options": {
"mode": "755"
}
},
...
]
$ findmnt | jc --findmnt -p -r
[
{
"target": "/",
"source": "/dev/mapper/centos-root",
"fstype": "xfs",
"options": "rw,relatime,seclabel,attr2,inode64,noquota"
},
{
"target": "/sys/fs/cgroup",
"source": "tmpfs",
"fstype": "tmpfs",
"options": "ro,nosuid,nodev,noexec,seclabel,mode=755"
},
...
]
<a id="jc.parsers.findmnt.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -40,13 +40,13 @@ Schema:
[
{
"commit": string,
"author": string,
"author_email": string,
"author": string/null,
"author_email": string/null,
"date": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"commit_by": string,
"commit_by_email": string,
"commit_by": string/null,
"commit_by_email": string/null,
"commit_by_date": string,
"message": string,
"stats" : {
@@ -61,7 +61,7 @@ Schema:
]
[0] naive timestamp if "date" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -172,4 +172,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -41,13 +41,13 @@ Schema:
{
"commit": string,
"author": string,
"author_email": string,
"author": string/null,
"author_email": string/null,
"date": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"commit_by": string,
"commit_by_email": string,
"commit_by": string/null,
"commit_by_email": string/null,
"commit_by_date": string,
"message": string,
"stats" : {
@@ -68,7 +68,7 @@ Schema:
}
[0] naive timestamp if "date" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -108,4 +108,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -0,0 +1,92 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.git_ls_remote"></a>
# jc.parsers.git\_ls\_remote
jc - JSON Convert `git ls-remote` command output parser
This parser outputs two schemas:
- Default: A single object with key/value pairs
- Raw: An array of objects (`--raw` (cli) or `raw=True (module))
See the Schema section for more details
Usage (cli):
$ git ls-remote | jc --git-ls-remote
or
$ jc git ls-remote
Usage (module):
import jc
result = jc.parse('git_ls_remote', git_ls_remote_command_output)
Schema:
Default:
{
<reference>: string
}
Raw:
[
{
"reference": string,
"commit": string
}
]
Examples:
$ git ls-remote | jc --git-ls-remote -p
{
"HEAD": "214cd6b9e09603b3c4fa02203b24fb2bc3d4e338",
"refs/heads/dev": "b884f6aacca39e05994596d8fdfa7e7c4f1e0389",
"refs/heads/master": "214cd6b9e09603b3c4fa02203b24fb2bc3d4e338",
"refs/pull/1/head": "e416c77bed1267254da972b0f95b7ff1d43fccef",
...
}
$ git ls-remote | jc --git-ls-remote -p -r
[
{
"reference": "HEAD",
"commit": "214cd6b9e09603b3c4fa02203b24fb2bc3d4e338"
},
{
"reference": "refs/heads/dev",
"commit": "b884f6aacca39e05994596d8fdfa7e7c4f1e0389"
},
...
]
<a id="jc.parsers.git_ls_remote.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> Union[JSONDictType, List[JSONDictType]]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary (default) or List of Dictionaries (raw)
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -5,7 +5,10 @@
jc - JSON Convert `ifconfig` command output parser
> Note: No `ifconfig` options are supported.
No `ifconfig` options are supported.
Consider using the `ip` command instead of `ifconfig` as it supports native
JSON output.
Usage (cli):
@@ -24,40 +27,92 @@ Schema:
[
{
"name": string,
"flags": integer,
"name": string,
"type": string,
"metric": integer
"flags": integer,
"state": [
string
string
],
"mtu": integer,
"ipv4_addr": string,
"ipv4_mask": string,
"ipv4_bcast": string,
"ipv6_addr": string,
"ipv6_mask": integer,
"ipv6_scope": string,
"mac_addr": string,
"type": string,
"rx_packets": integer,
"rx_bytes": integer,
"rx_errors": integer,
"rx_dropped": integer,
"rx_overruns": integer,
"rx_frame": integer,
"tx_packets": integer,
"tx_bytes": integer,
"tx_errors": integer,
"tx_dropped": integer,
"tx_overruns": integer,
"tx_carrier": integer,
"tx_collisions": integer,
"metric": integer
"mtu": integer,
"mac_addr": string,
"ipv4_addr": string, # [0]
"ipv4_mask": string, # [0]
"ipv4_bcast": string, # [0]
"ipv6_addr": string, # [0]
"ipv6_mask": integer, # [0]
"ipv6_scope": string, # [0]
"ipv6_scope_id": string, # [0]
"ipv6_type": string, # [0]
"rx_packets": integer,
"rx_bytes": integer,
"rx_errors": integer,
"rx_dropped": integer,
"rx_overruns": integer,
"rx_frame": integer,
"tx_packets": integer,
"tx_bytes": integer,
"tx_errors": integer,
"tx_dropped": integer,
"tx_overruns": integer,
"tx_carrier": integer,
"tx_collisions": integer,
"options": string,
"options_flags": [
string
],
"status": string,
"hw_address": string,
"media": string,
"media_flags": [
string
],
"nd6_options": integer,
"nd6_flags": [
string
],
"plugged": string,
"vendor": string,
"vendor_pn": string,
"vendor_sn": string,
"vendor_date": string,
"module_temperature": string,
"module_voltage": string
"ipv4": [
{
"address": string,
"mask": string,
"broadcast": string
}
],
"ipv6: [
{
"address": string,
"scope_id": string,
"mask": integer,
"scope": string,
"type": string
}
],
"lanes": [
{
"lane": integer,
"rx_power_mw": float,
"rx_power_dbm": float,
"tx_bias_ma": float
}
]
}
]
[0] these fields only pick up the last IP address in the interface
output and are here for backwards compatibility. For information on
all IP addresses, use the `ipv4` and `ipv6` objects which contain an
array of IP address objects.
Examples:
$ ifconfig | jc --ifconfig -p
$ ifconfig ens33 | jc --ifconfig -p
[
{
"name": "ens33",
@@ -69,120 +124,94 @@ Examples:
"MULTICAST"
],
"mtu": 1500,
"type": "Ethernet",
"mac_addr": "00:0c:29:3b:58:0e",
"ipv4_addr": "192.168.71.137",
"ipv4_mask": "255.255.255.0",
"ipv4_bcast": "192.168.71.255",
"ipv6_addr": "fe80::c1cb:715d:bc3e:b8a0",
"ipv6_mask": 64,
"ipv6_scope": "0x20",
"mac_addr": "00:0c:29:3b:58:0e",
"type": "Ethernet",
"ipv6_type": "link",
"metric": null,
"rx_packets": 8061,
"rx_bytes": 1514413,
"rx_errors": 0,
"rx_dropped": 0,
"rx_overruns": 0,
"rx_frame": 0,
"tx_packets": 4502,
"tx_errors": 0,
"tx_dropped": 0,
"tx_overruns": 0,
"tx_carrier": 0,
"tx_collisions": 0,
"rx_bytes": 1514413,
"tx_bytes": 866622,
"tx_errors": 0,
"tx_dropped": 0,
"tx_overruns": 0,
"tx_carrier": 0,
"tx_collisions": 0,
"metric": null
},
{
"name": "lo",
"flags": 73,
"state": [
"UP",
"LOOPBACK",
"RUNNING"
"ipv4": [
{
"address": "192.168.71.137",
"mask": "255.255.255.0",
"broadcast": "192.168.71.255"
}
],
"mtu": 65536,
"ipv4_addr": "127.0.0.1",
"ipv4_mask": "255.0.0.0",
"ipv4_bcast": null,
"ipv6_addr": "::1",
"ipv6_mask": 128,
"ipv6_scope": "0x10",
"mac_addr": null,
"type": "Local Loopback",
"rx_packets": 73,
"rx_bytes": 6009,
"rx_errors": 0,
"rx_dropped": 0,
"rx_overruns": 0,
"rx_frame": 0,
"tx_packets": 73,
"tx_bytes": 6009,
"tx_errors": 0,
"tx_dropped": 0,
"tx_overruns": 0,
"tx_carrier": 0,
"tx_collisions": 0,
"metric": null
"ipv6": [
{
"address": "fe80::c1cb:715d:bc3e:b8a0",
"scope_id": null,
"mask": 64,
"scope": "0x20",
"type": "link"
}
]
}
]
$ ifconfig | jc --ifconfig -p -r
$ ifconfig ens33 | jc --ifconfig -p -r
[
{
"name": "ens33",
"flags": "4163",
"state": "UP,BROADCAST,RUNNING,MULTICAST",
"mtu": "1500",
"type": "Ethernet",
"mac_addr": "00:0c:29:3b:58:0e",
"ipv4_addr": "192.168.71.137",
"ipv4_mask": "255.255.255.0",
"ipv4_bcast": "192.168.71.255",
"ipv6_addr": "fe80::c1cb:715d:bc3e:b8a0",
"ipv6_mask": "64",
"ipv6_scope": "0x20",
"mac_addr": "00:0c:29:3b:58:0e",
"type": "Ethernet",
"ipv6_type": "link",
"metric": null,
"rx_packets": "8061",
"rx_bytes": "1514413",
"rx_errors": "0",
"rx_dropped": "0",
"rx_overruns": "0",
"rx_frame": "0",
"tx_packets": "4502",
"tx_errors": "0",
"tx_dropped": "0",
"tx_overruns": "0",
"tx_carrier": "0",
"tx_collisions": "0",
"rx_bytes": "1514413",
"tx_bytes": "866622",
"tx_errors": "0",
"tx_dropped": "0",
"tx_overruns": "0",
"tx_carrier": "0",
"tx_collisions": "0",
"metric": null
},
{
"name": "lo",
"flags": "73",
"state": "UP,LOOPBACK,RUNNING",
"mtu": "65536",
"ipv4_addr": "127.0.0.1",
"ipv4_mask": "255.0.0.0",
"ipv4_bcast": null,
"ipv6_addr": "::1",
"ipv6_mask": "128",
"ipv6_scope": "0x10",
"mac_addr": null,
"type": "Local Loopback",
"rx_packets": "73",
"rx_bytes": "6009",
"rx_errors": "0",
"rx_dropped": "0",
"rx_overruns": "0",
"rx_frame": "0",
"tx_packets": "73",
"tx_bytes": "6009",
"tx_errors": "0",
"tx_dropped": "0",
"tx_overruns": "0",
"tx_carrier": "0",
"tx_collisions": "0",
"metric": null
"ipv4": [
{
"address": "192.168.71.137",
"mask": "255.255.255.0",
"broadcast": "192.168.71.255"
}
],
"ipv6": [
{
"address": "fe80::c1cb:715d:bc3e:b8a0",
"scope_id": null,
"mask": "64",
"scope": "0x20",
"type": "link"
}
]
}
]
@@ -191,7 +220,9 @@ Examples:
### parse
```python
def parse(data, raw=False, quiet=False)
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
@@ -209,4 +240,4 @@ Returns:
### Parser Information
Compatibility: linux, aix, freebsd, darwin
Version 1.12 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 2.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -3,13 +3,15 @@
# jc.parsers.ini
jc - JSON Convert `INI` file parser
jc - JSON Convert INI file parser
Parses standard `INI` files and files containing simple key/value pairs.
Parses standard INI files.
- Delimiter can be `=` or `:`. Missing values are supported.
- Comment prefix can be `#` or `;`. Comments must be on their own line.
- If duplicate keys are found, only the last value will be used.
- If any section names have the same name as a top-level key, the top-level
key will be overwritten by the section data.
> Note: Values starting and ending with double or single quotation marks
> will have the marks removed. If you would like to keep the quotation
@@ -27,45 +29,47 @@ Usage (module):
Schema:
ini or key/value document converted to a dictionary - see the configparser
INI document converted to a dictionary - see the python configparser
standard library documentation for more details.
{
"key1": string,
"key2": string
"<key1>": string,
"<key2>": string,
"<section1>": {
"<key1>": string,
"<key2>": string
},
"<section2>": {
"<key1>": string,
"<key2>": string
}
}
Examples:
$ cat example.ini
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
foo = fiz
bar = buz
[bitbucket.org]
User = hg
[section1]
fruit = apple
color = blue
[topsecret.server.com]
Port = 50022
ForwardX11 = no
[section2]
fruit = pear
color = green
$ cat example.ini | jc --ini -p
{
"bitbucket.org": {
"ServerAliveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "yes",
"User": "hg"
"foo": "fiz",
"bar": "buz",
"section1": {
"fruit": "apple",
"color": "blue"
},
"topsecret.server.com": {
"ServerAliveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "no",
"Port": "50022"
"section2": {
"fruit": "pear",
"color": "green"
}
}
@@ -87,9 +91,9 @@ Parameters:
Returns:
Dictionary representing the ini file
Dictionary representing the INI file.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 2.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

121
docs/parsers/ini_dup.md Normal file
View File

@@ -0,0 +1,121 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.ini_dup"></a>
# jc.parsers.ini\_dup
jc - JSON Convert INI with duplicate key file parser
Parses standard INI files and preserves duplicate values. All values are
contained in lists/arrays.
- Delimiter can be `=` or `:`. Missing values are supported.
- Comment prefix can be `#` or `;`. Comments must be on their own line.
- If any section names have the same name as a top-level key, the top-level
key will be overwritten by the section data.
- If multi-line values are used, each line will be a separate item in the
value list. Blank lines in multi-line values are not supported.
> Note: Values starting and ending with double or single quotation marks
> will have the marks removed. If you would like to keep the quotation
> marks, use the `-r` command-line argument or the `raw=True` argument in
> `parse()`.
Usage (cli):
$ cat foo.ini | jc --ini
Usage (module):
import jc
result = jc.parse('ini', ini_file_output)
Schema:
INI document converted to a dictionary - see the python configparser
standard library documentation for more details.
{
"<key1>": [
string
],
"<key2>": [
string
],
"<section1>": {
"<key1>": [
string
],
"<key2>": [
string
]
}
}
Examples:
$ cat example.ini
foo = fiz
bar = buz
[section1]
fruit = apple
color = blue
color = red
[section2]
fruit = pear
fruit = peach
color = green
$ cat example.ini | jc --ini -p
{
"foo": [
"fiz"
],
"bar": [
"buz"
],
"section1": {
"fruit": [
"apple"
],
"color": [
"blue",
"red"
]
},
"section2": {
"fruit": [
"pear",
"peach"
],
"color": [
"green"
]
}
}
<a id="jc.parsers.ini_dup.parse"></a>
### parse
```python
def parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary representing the INI file.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -130,4 +130,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -26,6 +26,9 @@ Schema:
"ip": string,
"ip_compressed": string,
"ip_exploded": string,
"ip_split": [
string
],
"scope_id": string/null,
"ipv4_mapped": string/null,
"six_to_four": string/null,
@@ -83,6 +86,12 @@ Examples:
"ip": "192.168.2.10",
"ip_compressed": "192.168.2.10",
"ip_exploded": "192.168.2.10",
"ip_split": [
"192",
"168",
"2",
"10"
],
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
@@ -138,6 +147,12 @@ Examples:
"ip": "192.168.2.10",
"ip_compressed": "192.168.2.10",
"ip_exploded": "192.168.2.10",
"ip_split": [
"192",
"168",
"2",
"10"
],
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
@@ -191,14 +206,24 @@ Examples:
"version": 6,
"max_prefix_length": 128,
"ip": "127:0:de::1",
"ip_compressed": "127:0:de::1%128",
"ip_compressed": "127:0:de::1",
"ip_exploded": "0127:0000:00de:0000:0000:0000:0000:0001",
"ip_split": [
"0127",
"0000",
"00de",
"0000",
"0000",
"0000",
"0000",
"0001"
],
"scope_id": "128",
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.....0.7.2.1.0.ip6.arpa",
"dns_ptr": "1.0.0.0.0.0...0.0.0.e.d.0.0.0.0.0.0.7.2.1.0.ip6.arpa",
"network": "127:0:de::",
"broadcast": "127:0:de::ffff:ffff",
"hostmask": "::ffff:ffff",
@@ -231,13 +256,13 @@ Examples:
"last_host": "01:27:00:00:00:de:00:00:00:00:00:00:ff:ff:ff:fe"
},
"bin": {
"ip": "000000010010011100000000000000000000000011011110000000...",
"network": "0000000100100111000000000000000000000000110111100...",
"broadcast": "00000001001001110000000000000000000000001101111...",
"hostmask": "000000000000000000000000000000000000000000000000...",
"netmask": "1111111111111111111111111111111111111111111111111...",
"first_host": "0000000100100111000000000000000000000000110111...",
"last_host": "00000001001001110000000000000000000000001101111..."
"ip": "0000000100100111000000000000000000000000110...000000000001",
"network": "00000001001001110000000000000000000000...000000000000",
"broadcast": "000000010010011100000000000000000000...111111111111",
"hostmask": "0000000000000000000000000000000000000...111111111111",
"netmask": "11111111111111111111111111111111111111...000000000000",
"first_host": "00000001001001110000000000000000000...000000000001",
"last_host": "000000010010011100000000000000000000...1111111111110"
}
}
@@ -248,12 +273,22 @@ Examples:
"ip": "127:0:de::1",
"ip_compressed": "127:0:de::1",
"ip_exploded": "0127:0000:00de:0000:0000:0000:0000:0001",
"ip_split": [
"0127",
"0000",
"00de",
"0000",
"0000",
"0000",
"0000",
"0001"
],
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "1.0.0.0.0.0.0....0.0.0.e.d.0.0.0.0.0.0.7.2.1.0.ip6.arpa",
"dns_ptr": "1.0.0.0.0.0....0.0.0.0.e.d.0.0.0.0.0.0.7.2.1.0.ip6.arpa",
"network": "127:0:de::1",
"broadcast": "127:0:de::1",
"hostmask": "::",
@@ -286,13 +321,13 @@ Examples:
"last_host": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01"
},
"bin": {
"ip": "0000000100100111000000000000000000000000110111100000000...",
"network": "00000001001001110000000000000000000000001101111000...",
"broadcast": "000000010010011100000000000000000000000011011110...",
"hostmask": "0000000000000000000000000000000000000000000000000...",
"netmask": "11111111111111111111111111111111111111111111111111...",
"first_host": "00000001001001110000000000000000000000001101111...",
"last_host": "000000010010011100000000000000000000000011011110..."
"ip": "0000000100100111000000000000000000000000110111100...000001",
"network": "00000001001001110000000000000000000000001101...000001",
"broadcast": "000000010010011100000000000000000000000011...000001",
"hostmask": "0000000000000000000000000000000000000000000...000000",
"netmask": "11111111111111111111111111111111111111111111...111111",
"first_host": "00000001001001110000000000000000000000001...000001",
"last_host": "000000010010011100000000000000000000000011...0000001"
}
}
@@ -304,12 +339,22 @@ Examples:
"ip": "::ffff:c0a8:123",
"ip_compressed": "::ffff:c0a8:123",
"ip_exploded": "0000:0000:0000:0000:0000:ffff:c0a8:0123",
"ip_split": [
"0000",
"0000",
"0000",
"0000",
"0000",
"ffff",
"c0a8",
"0123"
],
"scope_id": null,
"ipv4_mapped": "192.168.1.35",
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "3.2.1.0.8.a.0.c.f.f.f.f.0.0.0....0.0.0.0.0.0.0.ip6.arpa",
"dns_ptr": "3.2.1.0.8.a.0.c.f.f.f.f.0.0....0.0.0.0.0.0.ip6.arpa",
"network": "::ffff:c0a8:123",
"broadcast": "::ffff:c0a8:123",
"hostmask": "::",
@@ -342,13 +387,13 @@ Examples:
"last_host": "00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23"
},
"bin": {
"ip": "0000000000000000000000000000000000000000000000000000000...",
"network": "00000000000000000000000000000000000000000000000000...",
"broadcast": "000000000000000000000000000000000000000000000000...",
"hostmask": "0000000000000000000000000000000000000000000000000...",
"netmask": "11111111111111111111111111111111111111111111111111...",
"first_host": "00000000000000000000000000000000000000000000000...",
"last_host": "000000000000000000000000000000000000000000000000..."
"ip": "000000000000000000000000000000000000000000000...100100011",
"network": "0000000000000000000000000000000000000000...000100011",
"broadcast": "00000000000000000000000000000000000000...000100011",
"hostmask": "000000000000000000000000000000000000000...000000000",
"netmask": "1111111111111111111111111111111111111111...111111111",
"first_host": "0000000000000000000000000000000000000...100100011",
"last_host": "00000000000000000000000000000000000000...0100100011"
}
}
@@ -360,12 +405,22 @@ Examples:
"ip": "2002:c000:204::",
"ip_compressed": "2002:c000:204::",
"ip_exploded": "2002:c000:0204:0000:0000:0000:0000:0000",
"ip_split": [
"2002",
"c000",
"0204",
"0000",
"0000",
"0000",
"0000",
"0000"
],
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": "192.0.2.4",
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "0.0.0.0.0.0.0.0......0.4.0.2.0.0.0.0.c.2.0.0.2.ip6.arpa",
"dns_ptr": "0.0.0.0.0.0.0...0.0.0.4.0.2.0.0.0.0.c.2.0.0.2.ip6.arpa",
"network": "2002:c000:204::",
"broadcast": "2002:c000:204:ffff:ffff:ffff:ffff:ffff",
"hostmask": "::ffff:ffff:ffff:ffff:ffff",
@@ -398,13 +453,13 @@ Examples:
"last_host": "20:02:c0:00:02:04:ff:ff:ff:ff:ff:ff:ff:ff:ff:fe"
},
"bin": {
"ip": "0010000000000010110000000000000000000010000001000000000...",
"network": "00100000000000101100000000000000000000100000010000...",
"broadcast": "001000000000001011000000000000000000001000000100...",
"hostmask": "0000000000000000000000000000000000000000000000001...",
"netmask": "11111111111111111111111111111111111111111111111100...",
"first_host": "00100000000000101100000000000000000000100000010...",
"last_host": "001000000000001011000000000000000000001000000100..."
"ip": "00100000000000101100000000000000000000100000010...00000000",
"network": "001000000000001011000000000000000000001000...00000000",
"broadcast": "0010000000000010110000000000000000000010...11111111",
"hostmask": "00000000000000000000000000000000000000000...11111111",
"netmask": "111111111111111111111111111111111111111111...00000000",
"first_host": "001000000000001011000000000000000000001...00000001",
"last_host": "0010000000000010110000000000000000000010...111111110"
}
}
@@ -416,12 +471,22 @@ Examples:
"ip": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"ip_compressed": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"ip_exploded": "2001:0000:4136:e378:8000:63bf:3fff:fdd2",
"ip_split": [
"2001",
"0000",
"4136",
"e378",
"8000",
"63bf",
"3fff",
"fdd2"
],
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": "192.0.2.45",
"teredo_server": "65.54.227.120",
"dns_ptr": "2.d.d.f.f.f.f.3.f.b.3.6.0.0.0....0.0.0.1.0.0.2.ip6.arpa",
"dns_ptr": "2.d.d.f.f.f.f.3.f.b.3.6.0.0.0.8.8....0.1.0.0.2.ip6.arpa",
"network": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"broadcast": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"hostmask": "::",
@@ -454,13 +519,13 @@ Examples:
"last_host": "20:01:00:00:41:36:e3:78:80:00:63:bf:3f:ff:fd:d2"
},
"bin": {
"ip": "001000000000000100000000000000000100000100110110111000...",
"network": "0010000000000001000000000000000001000001001101101...",
"broadcast": "00100000000000010000000000000000010000010011011...",
"hostmask": "000000000000000000000000000000000000000000000000...",
"netmask": "1111111111111111111111111111111111111111111111111...",
"first_host": "0010000000000001000000000000000001000001001101...",
"last_host": "00100000000000010000000000000000010000010011011..."
"ip": "0010000000000001000000000000000001000001001...110111010010",
"network": "00100000000000010000000000000000010000...110111010010",
"broadcast": "001000000000000100000000000000000100...110111010010",
"hostmask": "0000000000000000000000000000000000000...000000000000",
"netmask": "11111111111111111111111111111111111111...111111111111",
"first_host": "00100000000000010000000000000000010...110111010010",
"last_host": "001000000000000100000000000000000100...110111010010"
}
}
@@ -487,4 +552,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -5,65 +5,10 @@
jc - JSON Convert ISO 8601 Datetime string parser
This parser supports standard ISO 8601 strings that include both date and
time. If no timezone or offset information is available in the sring, then
UTC timezone is used.
This parser has been renamed to datetime-iso (cli) or datetime_iso (module).
Usage (cli):
$ echo "2022-07-20T14:52:45Z" | jc --iso-datetime
Usage (module):
import jc
result = jc.parse('iso_datetime', iso_8601_string)
Schema:
{
"year": integer,
"month": string,
"month_num": integer,
"day": integer,
"weekday": string,
"weekday_num": integer,
"hour": integer,
"hour_24": integer,
"minute": integer,
"second": integer,
"microsecond": integer,
"period": string,
"utc_offset": string,
"day_of_year": integer,
"week_of_year": integer,
"iso": string,
"timestamp": integer # [0]
}
[0] timezone aware UNIX timestamp expressed in UTC
Examples:
$ echo "2022-07-20T14:52:45Z" | jc --iso-datetime -p
{
"year": 2022,
"month": "Jul",
"month_num": 7,
"day": 20,
"weekday": "Wed",
"weekday_num": 3,
"hour": 2,
"hour_24": 14,
"minute": 52,
"second": 45,
"microsecond": 0,
"period": "PM",
"utc_offset": "+0000",
"day_of_year": 201,
"week_of_year": 29,
"iso": "2022-07-20T14:52:45+00:00",
"timestamp": 1658328765
}
This parser will be removed in a future version, so please start using
the new parser name.
<a id="jc.parsers.iso_datetime.parse"></a>
@@ -73,7 +18,8 @@ Examples:
def parse(data, raw=False, quiet=False)
```
Main text parsing function
This parser is deprecated and calls datetime_iso. Please use datetime_iso
directly. This parser will be removed in the future.
Parameters:
@@ -88,4 +34,4 @@ Returns:
### Parser Information
Compatibility: linux, aix, freebsd, darwin, win32, cygwin
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

111
docs/parsers/iwconfig.md Normal file
View File

@@ -0,0 +1,111 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.iwconfig"></a>
# jc.parsers.iwconfig
jc - JSON Convert `iwconfig` command output parser
No `iwconfig` options are supported.
Usage (cli):
$ iwconfig | jc --iwconfig
or
$ jc iwconfig
Usage (module):
import jc
result = jc.parse('iwconfig', iwconfig_command_output)
Schema:
[
{
"name": string,
"protocol": string,
"essid": string,
"mode": string,
"frequency": float,
"frequency_unit": string,
"access_point": string,
"bit_rate": float,
"bit_rate_unit": string,
"tx_power": integer,
"tx_power_unit": string,
"retry_short_limit": integer,
"rts_threshold": boolean,
"fragment_threshold": boolean,
"power_management": boolean,
"link_quality": string,
"signal_level": integer,
"signal_level_unit": string,
"rx_invalid_nwid": integer,
"rx_invalid_crypt": integer,
"rx_invalid_frag": integer,
"tx_excessive_retries": integer,
"invalid_misc": integer,
"missed_beacon": integer
}
]
Examples:
$ iwconfig | jc --iwconfig -p
[
{
"name": "wlp5s0",
"protocol": "IEEE 802.11",
"essid": "BLABLABLA",
"mode": "Managed",
"frequency": 5.18,
"frequency_unit": "GHz",
"access_point": "E6:64:DA:16:51:BF",
"bit_rate": 6.0,
"bit_rate_unit": "Mb/s",
"tx_power": 30,
"tx_power_unit": "dBm",
"retry_short_limit": 7,
"rts_threshold": false,
"fragment_threshold": false,
"power_management": true,
"link_quality": "61/70",
"signal_level": -49,
"signal_level_unit": "dBm",
"rx_invalid_nwid": 0,
"rx_invalid_crypt": 0,
"rx_invalid_frag": 0,
"tx_excessive_retries": 0,
"invalid_misc": 2095,
"missed_beacon": 0
}
]
<a id="jc.parsers.iwconfig.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Thomas Vincent (vrince@gmail.com)

View File

@@ -3,7 +3,7 @@
# jc.parsers.kv
jc - JSON Convert `Key/Value` file parser
jc - JSON Convert `Key/Value` file and string parser
Supports files containing simple key/value pairs.
@@ -26,8 +26,8 @@ Usage (module):
Schema:
key/value document converted to a dictionary - see the configparser standard
library documentation for more details.
Key/Value document converted to a dictionary - see the python configparser
standard library documentation for more details.
{
"key1": string,
@@ -41,6 +41,7 @@ Examples:
name = John Doe
address=555 California Drive
age: 34
; comments can include # or ;
# delimiter can be = or :
# quoted values have quotation marks stripped by default
@@ -65,8 +66,6 @@ def parse(data, raw=False, quiet=False)
Main text parsing function
Note: this is just a wrapper for jc.parsers.ini
Parameters:
data: (string) text data to parse
@@ -75,9 +74,9 @@ Parameters:
Returns:
Dictionary representing the key/value file
Dictionary representing a Key/Value pair document.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 2.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -99,4 +99,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, aix, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

148
docs/parsers/lspci.md Normal file
View File

@@ -0,0 +1,148 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.lspci"></a>
# jc.parsers.lspci
jc - JSON Convert `lspci -mmv` command output parser
This parser supports the following `lspci` options:
- `-mmv`
- `-nmmv`
- `-nnmmv`
Usage (cli):
$ lspci -nnmmv | jc --lspci
or
$ jc lspci -nnmmv
Usage (module):
import jc
result = jc.parse('lspci', lspci_command_output)
Schema:
[
{
"slot": string,
"domain": string,
"domain_int": integer,
"bus": string,
"bus_int": integer,
"dev": string,
"dev_int": integer,
"function": string,
"function_int": integer,
"class": string,
"class_id": string,
"class_id_int": integer,
"vendor": string,
"vendor_id": string,
"vendor_id_int": integer,
"device": string,
"device_id": string,
"device_id_int": integer,
"svendor": string,
"svendor_id": string,
"svendor_id_int": integer,
"sdevice": string,
"sdevice_id": string,
"sdevice_id_int": integer,
"rev": string,
"physlot": string,
"physlot_int": integer,
"progif": string,
"progif_int": integer
}
]
Examples:
$ lspci -nnmmv | jc --lspci -p
[
{
"slot": "ff:02:05.0",
"domain": "ff",
"domain_int": 255,
"bus": "02",
"bus_int": 2,
"dev": "05",
"dev_int": 5,
"function": "0",
"function_int": 0,
"class": "SATA controller",
"class_id": "0106",
"class_id_int": 262,
"vendor": "VMware",
"vendor_id": "15ad",
"vendor_id_int": 5549,
"device": "SATA AHCI controller",
"device_id": "07e0",
"device_id_int": 2016,
"svendor": "VMware",
"svendor_id": "15ad",
"svendor_id_int": 5549,
"sdevice": "SATA AHCI controller",
"sdevice_id": "07e0",
"sdevice_id_int": 2016,
"physlot": "37",
"physlot_int": 55,
"progif": "01",
"progif_int": 1
},
...
]
$ lspci -nnmmv | jc --lspci -p -r
[
{
"slot": "ff:02:05.0",
"domain": "ff",
"bus": "02",
"dev": "05",
"function": "0",
"class": "SATA controller",
"class_id": "0106",
"vendor": "VMware",
"vendor_id": "15ad",
"device": "SATA AHCI controller",
"device_id": "07e0",
"svendor": "VMware",
"svendor_id": "15ad",
"sdevice": "SATA AHCI controller",
"sdevice_id": "07e0",
"physlot": "37",
"progif": "01"
},
...
]
<a id="jc.parsers.lspci.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -102,6 +102,28 @@ Schema:
]
}
},
"videocontrol_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
}
],
"videostreaming_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
}
],
"endpoint_descriptors": [
{
"<item>": {
@@ -290,4 +312,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -25,7 +25,7 @@ Schema:
"filesystem": string,
"mount_point": string,
"type": string,
"access": [
"options": [
string
]
}
@@ -39,7 +39,7 @@ Example:
"filesystem": "sysfs",
"mount_point": "/sys",
"type": "sysfs",
"access": [
"options": [
"rw",
"nosuid",
"nodev",
@@ -51,7 +51,7 @@ Example:
"filesystem": "proc",
"mount_point": "/proc",
"type": "proc",
"access": [
"options": [
"rw",
"nosuid",
"nodev",
@@ -63,7 +63,7 @@ Example:
"filesystem": "udev",
"mount_point": "/dev",
"type": "devtmpfs",
"access": [
"options": [
"rw",
"nosuid",
"relatime",
@@ -96,6 +96,6 @@ Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, freebsd
Compatibility: linux, darwin, freebsd, aix
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)

178
docs/parsers/openvpn.md Normal file
View File

@@ -0,0 +1,178 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.openvpn"></a>
# jc.parsers.openvpn
jc - JSON Convert openvpn-status.log file parser
The `*_epoch` calculated timestamp fields are naive. (i.e. based on
the local time of the system the parser is run on)
Usage (cli):
$ cat openvpn-status.log | jc --openvpn
Usage (module):
import jc
result = jc.parse('openvpn', openvpn_status_log_file_output)
Schema:
{
"clients": [
{
"common_name": string,
"real_address": string,
"real_address_prefix": integer, # [0]
"real_address_port": integer, # [0]
"bytes_received": integer,
"bytes_sent": integer,
"connected_since": string,
"connected_since_epoch": integer,
"updated": string,
"updated_epoch": integer,
}
],
"routing_table": [
{
"virtual_address": string,
"virtual_address_prefix": integer, # [0]
"virtual_address_port": integer, # [0]
"common_name": string,
"real_address": string,
"real_address_prefix": integer, # [0]
"real_address_port": integer, # [0]
"last_reference": string,
"last_reference_epoch": integer,
}
],
"global_stats": {
"max_bcast_mcast_queue_len": integer
}
}
[0] null/None if not found
Examples:
$ cat openvpn-status.log | jc --openvpn -p
{
"clients": [
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10",
"bytes_received": 334948,
"bytes_sent": 1973012,
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015",
"real_address_prefix": null,
"real_address_port": 49502,
"connected_since_epoch": 1434626583,
"updated_epoch": 1434640335
},
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10",
"bytes_received": 334948,
"bytes_sent": 1973012,
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015",
"real_address_prefix": null,
"real_address_port": 49503,
"connected_since_epoch": 1434626583,
"updated_epoch": 1434640335
}
],
"routing_table": [
{
"virtual_address": "192.168.255.118",
"common_name": "baz@example.com",
"real_address": "10.10.10.10",
"last_reference": "Thu Jun 18 08:12:09 2015",
"virtual_address_prefix": null,
"virtual_address_port": null,
"real_address_prefix": null,
"real_address_port": 63414,
"last_reference_epoch": 1434640329
},
{
"virtual_address": "10.200.0.0",
"common_name": "baz@example.com",
"real_address": "10.10.10.10",
"last_reference": "Thu Jun 18 08:12:09 2015",
"virtual_address_prefix": 16,
"virtual_address_port": null,
"real_address_prefix": null,
"real_address_port": 63414,
"last_reference_epoch": 1434640329
}
],
"global_stats": {
"max_bcast_mcast_queue_len": 0
}
}
$ cat openvpn-status.log | jc --openvpn -p -r
{
"clients": [
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10:49502",
"bytes_received": "334948",
"bytes_sent": "1973012",
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015"
},
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10:49503",
"bytes_received": "334948",
"bytes_sent": "1973012",
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015"
}
],
"routing_table": [
{
"virtual_address": "192.168.255.118",
"common_name": "baz@example.com",
"real_address": "10.10.10.10:63414",
"last_reference": "Thu Jun 18 08:12:09 2015"
},
{
"virtual_address": "10.200.0.0/16",
"common_name": "baz@example.com",
"real_address": "10.10.10.10:63414",
"last_reference": "Thu Jun 18 08:12:09 2015"
}
],
"global_stats": {
"max_bcast_mcast_queue_len": "0"
}
}
<a id="jc.parsers.openvpn.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

66
docs/parsers/os_prober.md Normal file
View File

@@ -0,0 +1,66 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.os_prober"></a>
# jc.parsers.os\_prober
jc - JSON Convert `os-prober` command output parser
Usage (cli):
$ os-prober | jc --os-prober
or
$ jc os-prober
Usage (module):
import jc
result = jc.parse('os_prober', os_prober_command_output)
Schema:
{
"partition": string,
"efi_bootmgr": string, # [0]
"name": string,
"short_name": string,
"type": string
}
[0] only exists if an EFI boot manager is detected
Examples:
$ os-prober | jc --os-prober -p
{
"partition": "/dev/sda1",
"name": "Windows 10",
"short_name": "Windows",
"type": "chain"
}
<a id="jc.parsers.os_prober.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

99
docs/parsers/pci_ids.md Normal file
View File

@@ -0,0 +1,99 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.pci_ids"></a>
# jc.parsers.pci\_ids
jc - JSON Convert `pci.ids` file parser
This parser converts the pci.ids database file.
https://raw.githubusercontent.com/pciutils/pciids/master/pci.ids
A nested schema allows straightforward queries with tools like `jq`. Hex id
numbers are prefixed with an underscore (`_`) so bracket notation is not
necessary when referencing. For example:
$ cat pci.ids | jc --pci-ids | jq '.vendors._9005._0053._9005._ffff.subsystem_name'
"AIC-7896 SCSI Controller mainboard implementation"
Here are the vendor and class mappings:
jq '.vendors._001c._0001._001c._0005.subsystem_name'
| | | |
| | | subdevice
| | subvendor
| device
vendor
jq '.classes._0c._03._40'
| | |
| | prog_if
| subclass
class
Usage (cli):
$ cat pci.ids | jc --pci-ids
Usage (module):
import jc
result = jc.parse('pci_ids', pci_ids_file_output)
Schema:
{
"vendors": {
"_<vendor_id>": {
"vendor_name": string,
"_<device_id>": {
"device_name": string,
"_<subvendor_id>": {
"_<subdevice_id": string
}
}
}
},
"classes": {
"_<class_id>": {
"class_name": string,
"_<subclass_id>": {
"subclass_name": string,
"_<prog_if>": string
}
}
}
}
Examples:
$ cat pci.ids | jc --pci-ids | jq '.vendors._001c._0001._001c._0005.subsystem_name'
"2 Channel CAN Bus SJC1000 (Optically Isolated)"
$ cat pci.ids | jc --pci-ids | jq '.classes._0c._03._40'
"USB4 Host Interface"
<a id="jc.parsers.pci_ids.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

75
docs/parsers/pgpass.md Normal file
View File

@@ -0,0 +1,75 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.pgpass"></a>
# jc.parsers.pgpass
jc - JSON Convert PostgreSQL password file parser
Usage (cli):
$ cat /var/lib/postgresql/.pgpass | jc --pgpass
Usage (module):
import jc
result = jc.parse('pgpass', postgres_password_file)
Schema:
[
{
"hostname": string,
"port": string,
"database": string,
"username": string,
"password": string
}
]
Examples:
$ cat /var/lib/postgresql/.pgpass | jc --pgpass -p
[
{
"hostname": "dbserver",
"port": "*",
"database": "db1",
"username": "dbuser",
"password": "pwd123"
},
{
"hostname": "dbserver2",
"port": "8888",
"database": "inventory",
"username": "joe:user",
"password": "abc123"
},
...
]
<a id="jc.parsers.pgpass.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -106,4 +106,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -5,7 +5,7 @@
jc - JSON Convert PLIST file parser
Converts binary and XML PLIST files.
Converts binary, XML, and NeXTSTEP PLIST files.
Binary values are converted into an ASCII hex representation.
@@ -69,9 +69,9 @@ Parameters:
Returns:
List of Dictionaries. Raw or processed structured data.
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -6,7 +6,7 @@
jc - JSON Convert Proc file output parser
This parser automatically identifies the Proc file and calls the
corresponding parser to peform the parsing.
corresponding parser to perform the parsing.
Magic syntax for converting `/proc` files is also supported by running
`jc /proc/<path to file>`. Any `jc` options must be specified before the
@@ -85,7 +85,7 @@ Examples:
...
]
$ proc_modules | jc --proc_modules -p -r
$ cat /proc/modules | jc --proc-modules -p -r
[
{
"module": "binfmt_misc",
@@ -139,4 +139,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -223,4 +223,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -114,4 +114,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

75
docs/parsers/semver.md Normal file
View File

@@ -0,0 +1,75 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.semver"></a>
# jc.parsers.semver
jc - JSON Convert Semantic Version string parser
This parser conforms to the specification at https://semver.org/
Usage (cli):
$ echo 1.2.3-rc.1+44837 | jc --semver
Usage (module):
import jc
result = jc.parse('semver', semver_string)
Schema:
Strings that do not strictly conform to the specification will return an
empty object.
{
"major": integer,
"minor": integer,
"patch": integer,
"prerelease": string/null,
"build": string/null
}
Examples:
$ echo 1.2.3-rc.1+44837 | jc --semver -p
{
"major": 1,
"minor": 2,
"patch": 3,
"prerelease": "rc.1",
"build": "44837"
}
$ echo 1.2.3-rc.1+44837 | jc --semver -p -r
{
"major": "1",
"minor": "2",
"patch": "3",
"prerelease": "rc.1",
"build": "44837"
}
<a id="jc.parsers.semver.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

507
docs/parsers/sshd_conf.md Normal file
View File

@@ -0,0 +1,507 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.sshd_conf"></a>
# jc.parsers.sshd\_conf
jc - JSON Convert sshd configuration file and `sshd -T` command output parser
This parser will work with `sshd` configuration files or the output of
`sshd -T`. Any `Match` blocks in the `sshd` configuration file will be
ignored.
Usage (cli):
$ sshd -T | jc --sshd-conf
or
$ jc sshd -T
or
$ cat sshd_conf | jc --sshd-conf
Usage (module):
import jc
result = jc.parse('sshd_conf', sshd_conf_output)
Schema:
{
"acceptenv": [
string
],
"addressfamily": string,
"allowagentforwarding": string,
"allowstreamlocalforwarding": string,
"allowtcpforwarding": string,
"authenticationmethods": string,
"authorizedkeyscommand": string,
"authorizedkeyscommanduser": string,
"authorizedkeysfile": [
string
],
"authorizedprincipalscommand": string,
"authorizedprincipalscommanduser": string,
"authorizedprincipalsfile": string,
"banner": string,
"casignaturealgorithms": [
string
],
"chrootdirectory": string,
"ciphers": [
string
],
"ciphers_strategy": string,
"clientalivecountmax": integer,
"clientaliveinterval": integer,
"compression": string,
"disableforwarding": string,
"exposeauthinfo": string,
"fingerprinthash": string,
"forcecommand": string,
"gatewayports": string,
"gssapiauthentication": string,
"gssapicleanupcredentials": string,
"gssapikexalgorithms": [
string
],
"gssapikeyexchange": string,
"gssapistorecredentialsonrekey": string,
"gssapistrictacceptorcheck": string,
"hostbasedacceptedalgorithms": [
string
],
"hostbasedauthentication": string,
"hostbasedusesnamefrompacketonly": string,
"hostkeyagent": string,
"hostkeyalgorithms": [
string
],
"hostkey": [
string
],
"ignorerhosts": string,
"ignoreuserknownhosts": string,
"include": [
string
],
"ipqos": [
string
],
"kbdinteractiveauthentication": string,
"kerberosauthentication": string,
"kerberosorlocalpasswd": string,
"kerberosticketcleanup": sttring,
"kexalgorithms": [
string
],
"listenaddress": [
string
],
"logingracetime": integer,
"loglevel": string,
"macs": [
string
],
"macs_strategy": string,
"maxauthtries": integer,
"maxsessions": integer,
"maxstartups": integer,
"maxstartups_rate": integer,
"maxstartups_full": integer,
"modulifile": string,
"passwordauthentication": string,
"permitemptypasswords": string,
"permitlisten": [
string
],
"permitopen": [
string
],
"permitrootlogin": string,
"permittty": string,
"permittunnel": string,
"permituserenvironment": string,
"permituserrc": string,
"persourcemaxstartups": string,
"persourcenetblocksize": string,
"pidfile": string,
"port": [
integer
],
"printlastlog": string,
"printmotd": string,
"pubkeyacceptedalgorithms": [
string
],
"pubkeyauthentication": string,
"pubkeyauthoptions": string,
"rekeylimit": integer,
"rekeylimit_time": integer,
"revokedkeys": string,
"securitykeyprovider": string,
"streamlocalbindmask": string,
"streamlocalbindunlink": string,
"strictmodes": string,
"subsystem": string,
"subsystem_command": string
"syslogfacility": string,
"tcpkeepalive": string,
"trustedusercakeys": string,
"usedns": string,
"usepam": string,
"versionaddendum": string,
"x11displayoffset": integer,
"x11forwarding": string,
"x11uselocalhost": string,
"xauthlocation": string
}
Examples:
$ sshd -T | jc --sshd-conf -p
{
"acceptenv": [
"LANG",
"LC_*"
],
"addressfamily": "any",
"allowagentforwarding": "yes",
"allowstreamlocalforwarding": "yes",
"allowtcpforwarding": "yes",
"authenticationmethods": "any",
"authorizedkeyscommand": "none",
"authorizedkeyscommanduser": "none",
"authorizedkeysfile": [
".ssh/authorized_keys",
".ssh/authorized_keys2"
],
"authorizedprincipalscommand": "none",
"authorizedprincipalscommanduser": "none",
"authorizedprincipalsfile": "none",
"banner": "none",
"casignaturealgorithms": [
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"sk-ssh-ed25519@openssh.com",
"sk-ecdsa-sha2-nistp256@openssh.com",
"rsa-sha2-512",
"rsa-sha2-256"
],
"chrootdirectory": "none",
"ciphers": [
"chacha20-poly1305@openssh.com",
"aes128-ctr",
"aes192-ctr",
"aes256-ctr",
"aes128-gcm@openssh.com",
"aes256-gcm@openssh.com"
],
"ciphers_strategy": "+",
"clientalivecountmax": 3,
"clientaliveinterval": 0,
"compression": "yes",
"disableforwarding": "no",
"exposeauthinfo": "no",
"fingerprinthash": "SHA256",
"forcecommand": "none",
"gatewayports": "no",
"gssapiauthentication": "no",
"gssapicleanupcredentials": "yes",
"gssapikexalgorithms": [
"gss-group14-sha256-",
"gss-group16-sha512-",
"gss-nistp256-sha256-",
"gss-curve25519-sha256-",
"gss-group14-sha1-",
"gss-gex-sha1-"
],
"gssapikeyexchange": "no",
"gssapistorecredentialsonrekey": "no",
"gssapistrictacceptorcheck": "yes",
"hostbasedacceptedalgorithms": [
"ssh-ed25519-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
"sk-ssh-ed25519-cert-v01@openssh.com",
"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com",
"rsa-sha2-512-cert-v01@openssh.com",
"rsa-sha2-256-cert-v01@openssh.com",
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"sk-ssh-ed25519@openssh.com",
"sk-ecdsa-sha2-nistp256@openssh.com",
"rsa-sha2-512",
"rsa-sha2-256"
],
"hostbasedauthentication": "no",
"hostbasedusesnamefrompacketonly": "no",
"hostkeyagent": "none",
"hostkeyalgorithms": [
"ssh-ed25519-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
"sk-ssh-ed25519-cert-v01@openssh.com",
"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com",
"rsa-sha2-512-cert-v01@openssh.com",
"rsa-sha2-256-cert-v01@openssh.com",
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"sk-ssh-ed25519@openssh.com",
"sk-ecdsa-sha2-nistp256@openssh.com",
"rsa-sha2-512",
"rsa-sha2-256"
],
"hostkey": [
"/etc/ssh/ssh_host_ecdsa_key",
"/etc/ssh/ssh_host_ed25519_key",
"/etc/ssh/ssh_host_rsa_key"
],
"ignorerhosts": "yes",
"ignoreuserknownhosts": "no",
"ipqos": [
"lowdelay",
"throughput"
],
"kbdinteractiveauthentication": "no",
"kerberosauthentication": "no",
"kerberosorlocalpasswd": "yes",
"kerberosticketcleanup": "yes",
"kexalgorithms": [
"sntrup761x25519-sha512@openssh.com",
"curve25519-sha256",
"curve25519-sha256@libssh.org",
"ecdh-sha2-nistp256",
"ecdh-sha2-nistp384",
"ecdh-sha2-nistp521",
"diffie-hellman-group-exchange-sha256",
"diffie-hellman-group16-sha512",
"diffie-hellman-group18-sha512",
"diffie-hellman-group14-sha256"
],
"listenaddress": [
"0.0.0.0:22",
"[::]:22"
],
"logingracetime": 120,
"loglevel": "INFO",
"macs": [
"umac-64-etm@openssh.com",
"umac-128-etm@openssh.com",
"hmac-sha2-256-etm@openssh.com",
"hmac-sha2-512-etm@openssh.com",
"hmac-sha1-etm@openssh.com",
"umac-64@openssh.com",
"umac-128@openssh.com",
"hmac-sha2-256",
"hmac-sha2-512",
"hmac-sha1"
],
"macs_strategy": "^",
"maxauthtries": 6,
"maxsessions": 10,
"maxstartups": 10,
"modulifile": "/etc/ssh/moduli",
"passwordauthentication": "yes",
"permitemptypasswords": "no",
"permitlisten": [
"any"
],
"permitopen": [
"any"
],
"permitrootlogin": "without-password",
"permittty": "yes",
"permittunnel": "no",
"permituserenvironment": "no",
"permituserrc": "yes",
"persourcemaxstartups": "none",
"persourcenetblocksize": "32:128",
"pidfile": "/run/sshd.pid",
"port": [
22
],
"printlastlog": "yes",
"printmotd": "no",
"pubkeyacceptedalgorithms": [
"ssh-ed25519-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
"sk-ssh-ed25519-cert-v01@openssh.com",
"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com",
"rsa-sha2-512-cert-v01@openssh.com",
"rsa-sha2-256-cert-v01@openssh.com",
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"sk-ssh-ed25519@openssh.com",
"sk-ecdsa-sha2-nistp256@openssh.com",
"rsa-sha2-512",
"rsa-sha2-256"
],
"pubkeyauthentication": "yes",
"pubkeyauthoptions": "none",
"rekeylimit": 0,
"revokedkeys": "none",
"securitykeyprovider": "internal",
"streamlocalbindmask": "0177",
"streamlocalbindunlink": "no",
"strictmodes": "yes",
"subsystem": "sftp",
"syslogfacility": "AUTH",
"tcpkeepalive": "yes",
"trustedusercakeys": "none",
"usedns": "no",
"usepam": "yes",
"versionaddendum": "none",
"x11displayoffset": 10,
"x11forwarding": "yes",
"x11uselocalhost": "yes",
"xauthlocation": "/usr/bin/xauth",
"maxstartups_rate": 30,
"maxstartups_full": 100,
"rekeylimit_time": 0,
"subsystem_command": "/usr/lib/openssh/sftp-server"
}
$ sshd -T | jc --sshd-conf -p -r
{
"acceptenv": [
"LANG",
"LC_*"
],
"addressfamily": "any",
"allowagentforwarding": "yes",
"allowstreamlocalforwarding": "yes",
"allowtcpforwarding": "yes",
"authenticationmethods": "any",
"authorizedkeyscommand": "none",
"authorizedkeyscommanduser": "none",
"authorizedkeysfile": ".ssh/authorized_keys .ssh/authorized_keys2",
"authorizedprincipalscommand": "none",
"authorizedprincipalscommanduser": "none",
"authorizedprincipalsfile": "none",
"banner": "none",
"casignaturealgorithms": "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-s...",
"chrootdirectory": "none",
"ciphers": "chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,...",
"ciphers_strategy": "+",
"clientalivecountmax": "3",
"clientaliveinterval": "0",
"compression": "yes",
"disableforwarding": "no",
"exposeauthinfo": "no",
"fingerprinthash": "SHA256",
"forcecommand": "none",
"gatewayports": "no",
"gssapiauthentication": "no",
"gssapicleanupcredentials": "yes",
"gssapikexalgorithms": "gss-group14-sha256-,gss-group16-sha512-,...",
"gssapikeyexchange": "no",
"gssapistorecredentialsonrekey": "no",
"gssapistrictacceptorcheck": "yes",
"hostbasedacceptedalgorithms": "ssh-ed25519-cert-v01@openssh.co...",
"hostbasedauthentication": "no",
"hostbasedusesnamefrompacketonly": "no",
"hostkeyagent": "none",
"hostkeyalgorithms": "ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2...",
"hostkey": [
"/etc/ssh/ssh_host_ecdsa_key",
"/etc/ssh/ssh_host_ed25519_key",
"/etc/ssh/ssh_host_rsa_key"
],
"ignorerhosts": "yes",
"ignoreuserknownhosts": "no",
"ipqos": "lowdelay throughput",
"kbdinteractiveauthentication": "no",
"kerberosauthentication": "no",
"kerberosorlocalpasswd": "yes",
"kerberosticketcleanup": "yes",
"kexalgorithms": "sntrup761x25519-sha512@openssh.com,curve25519...",
"listenaddress": [
"0.0.0.0:22",
"[::]:22"
],
"logingracetime": "120",
"loglevel": "INFO",
"macs": "umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac...",
"macs_strategy": "^",
"maxauthtries": "6",
"maxsessions": "10",
"maxstartups": "10:30:100",
"modulifile": "/etc/ssh/moduli",
"passwordauthentication": "yes",
"permitemptypasswords": "no",
"permitlisten": "any",
"permitopen": "any",
"permitrootlogin": "without-password",
"permittty": "yes",
"permittunnel": "no",
"permituserenvironment": "no",
"permituserrc": "yes",
"persourcemaxstartups": "none",
"persourcenetblocksize": "32:128",
"pidfile": "/run/sshd.pid",
"port": [
"22"
],
"printlastlog": "yes",
"printmotd": "no",
"pubkeyacceptedalgorithms": "ssh-ed25519-cert-v01@openssh.com,...",
"pubkeyauthentication": "yes",
"pubkeyauthoptions": "none",
"rekeylimit": "0 0",
"revokedkeys": "none",
"securitykeyprovider": "internal",
"streamlocalbindmask": "0177",
"streamlocalbindunlink": "no",
"strictmodes": "yes",
"subsystem": "sftp /usr/lib/openssh/sftp-server",
"syslogfacility": "AUTH",
"tcpkeepalive": "yes",
"trustedusercakeys": "none",
"usedns": "no",
"usepam": "yes",
"versionaddendum": "none",
"x11displayoffset": "10",
"x11forwarding": "yes",
"x11uselocalhost": "yes",
"xauthlocation": "/usr/bin/xauth"
}
<a id="jc.parsers.sshd_conf.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -83,7 +83,10 @@ Examples:
```python
@add_jc_meta
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
def parse(data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False) -> StreamingOutputType
```
Main text parsing generator function. Returns an iterable object.
@@ -104,4 +107,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -53,7 +53,7 @@ Blank values converted to `null`/`None`.
]
[0] naive timestamp if "timestamp" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
[2] this field exists if the syslog line is not parsable. The value
is the original syslog line.

View File

@@ -64,7 +64,7 @@ Blank values converted to `null`/`None`.
}
[0] naive timestamp if "timestamp" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
[2] this field exists if the syslog line is not parsable. The value
is the original syslog line.

81
docs/parsers/toml.md Normal file
View File

@@ -0,0 +1,81 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.toml"></a>
# jc.parsers.toml
jc - JSON Convert TOML file parser
Usage (cli):
$ cat file.toml | jc --toml
Usage (module):
import jc
result = jc.parse('toml', toml_file_output)
Schema:
TOML Document converted to a Dictionary.
See https://toml.io/en/ for details.
{
"key1": string/int/float/boolean/null/array/object,
"key2": string/int/float/boolean/null/array/object
}
Examples:
$ cat file.toml
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00
[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
$ cat file.toml | jc --toml -p
{
"title": "TOML Example",
"owner": {
"name": "Tom Preston-Werner",
"dob": 296667120,
"dob_iso": "1979-05-27T07:32:00-08:00"
},
"database": {
"enabled": true,
"ports": [
8000,
8001,
8002
]
}
}
<a id="jc.parsers.toml.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

143
docs/parsers/udevadm.md Normal file
View File

@@ -0,0 +1,143 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.udevadm"></a>
# jc.parsers.udevadm
jc - JSON Convert `udevadm info` command output parser
Usage (cli):
$ udevadm info --query=all /dev/sda | jc --udevadm
or
$ jc udevadm info --query=all /dev/sda
Usage (module):
import jc
result = jc.parse('udevadm', udevadm_command_output)
Schema:
{
"P": string,
"N": string,
"L": integer,
"S": [
string
],
"E": {
"<key>": string
}
}
Examples:
$ udevadm info --query=all /dev/sda | jc --udevadm -p
{
"P": "/devices/pci0000:00/0000:00:10.0/host32/target32:0:0/32:0:0:0/block/sda",
"N": "sda",
"L": 0,
"S": [
"disk/by-path/pci-0000:00:10.0-scsi-0:0:0:0"
],
"E": {
"DEVPATH": "/devices/pci0000:00/0000:00:10.0/host32/target32:0:0/32:0:0:0/block/sda",
"DEVNAME": "/dev/sda",
"DEVTYPE": "disk",
"MAJOR": "8",
"MINOR": "0",
"SUBSYSTEM": "block",
"USEC_INITIALIZED": "6100111",
"SCSI_TPGS": "0",
"SCSI_TYPE": "disk",
"SCSI_VENDOR": "VMware,",
"SCSI_VENDOR_ENC": "VMware,\\x20",
"SCSI_MODEL": "VMware_Virtual_S",
"SCSI_MODEL_ENC": "VMware\\x20Virtual\\x20S",
"SCSI_REVISION": "1.0",
"ID_SCSI": "1",
"ID_VENDOR": "VMware_",
"ID_VENDOR_ENC": "VMware\\x2c\\x20",
"ID_MODEL": "VMware_Virtual_S",
"ID_MODEL_ENC": "VMware\\x20Virtual\\x20S",
"ID_REVISION": "1.0",
"ID_TYPE": "disk",
"MPATH_SBIN_PATH": "/sbin",
"ID_BUS": "scsi",
"ID_PATH": "pci-0000:00:10.0-scsi-0:0:0:0",
"ID_PATH_TAG": "pci-0000_00_10_0-scsi-0_0_0_0",
"ID_PART_TABLE_UUID": "a5bd0c01-4210-46f2-b558-5c11c209a8f7",
"ID_PART_TABLE_TYPE": "gpt",
"DEVLINKS": "/dev/disk/by-path/pci-0000:00:10.0-scsi-0:0:0:0",
"TAGS": ":systemd:"
}
}
$ udevadm info --query=all /dev/sda | jc --udevadm -p -r
{
"P": "/devices/pci0000:00/0000:00:10.0/host32/target32:0:0/32:0:0:0/block/sda",
"N": "sda",
"L": "0",
"S": [
"disk/by-path/pci-0000:00:10.0-scsi-0:0:0:0"
],
"E": {
"DEVPATH": "/devices/pci0000:00/0000:00:10.0/host32/target32:0:0/32:0:0:0/block/sda",
"DEVNAME": "/dev/sda",
"DEVTYPE": "disk",
"MAJOR": "8",
"MINOR": "0",
"SUBSYSTEM": "block",
"USEC_INITIALIZED": "6100111",
"SCSI_TPGS": "0",
"SCSI_TYPE": "disk",
"SCSI_VENDOR": "VMware,",
"SCSI_VENDOR_ENC": "VMware,\\x20",
"SCSI_MODEL": "VMware_Virtual_S",
"SCSI_MODEL_ENC": "VMware\\x20Virtual\\x20S",
"SCSI_REVISION": "1.0",
"ID_SCSI": "1",
"ID_VENDOR": "VMware_",
"ID_VENDOR_ENC": "VMware\\x2c\\x20",
"ID_MODEL": "VMware_Virtual_S",
"ID_MODEL_ENC": "VMware\\x20Virtual\\x20S",
"ID_REVISION": "1.0",
"ID_TYPE": "disk",
"MPATH_SBIN_PATH": "/sbin",
"ID_BUS": "scsi",
"ID_PATH": "pci-0000:00:10.0-scsi-0:0:0:0",
"ID_PATH_TAG": "pci-0000_00_10_0-scsi-0_0_0_0",
"ID_PART_TABLE_UUID": "a5bd0c01-4210-46f2-b558-5c11c209a8f7",
"ID_PART_TABLE_TYPE": "gpt",
"DEVLINKS": "/dev/disk/by-path/pci-0000:00:10.0-scsi-0:0:0:0",
"TAGS": ":systemd:"
}
}
<a id="jc.parsers.udevadm.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -123,4 +123,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -32,6 +32,7 @@ Schema:
"tbs_certificate": {
"version": string,
"serial_number": string, # [0]
"serial_number_str": string,
"signature": {
"algorithm": string,
"parameters": string/null,
@@ -43,7 +44,9 @@ Schema:
"organization_name": array/string,
"organizational_unit_name": array/string,
"common_name": string,
"email_address": string
"email_address": string,
"serial_number": string, # [0]
"serial_number_str": string
},
"validity": {
"not_before": integer, # [1]
@@ -58,7 +61,9 @@ Schema:
"organization_name": array/string,
"organizational_unit_name": array/string,
"common_name": string,
"email_address": string
"email_address": string,
"serial_number": string, # [0]
"serial_number_str": string
},
"subject_public_key_info": {
"algorithm": {
@@ -428,4 +433,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -5,6 +5,11 @@
jc - JSON Convert `XML` file parser
This parser adds a `@` prefix to attributes by default. This can be changed
to a `_` prefix by using the `-r` (cli) or `raw=True` (module) option.
Text values for nodes will have the key-name of `#text`.
Usage (cli):
$ cat foo.xml | jc --xml
@@ -93,4 +98,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -18,8 +18,8 @@ Usage (module):
Schema:
YAML Document converted to a Dictionary
See https://pypi.org/project/ruamel.yaml for details
YAML Document converted to a Dictionary.
See https://pypi.org/project/ruamel.yaml for details.
[
{
@@ -30,7 +30,7 @@ Schema:
Examples:
$ cat istio-mtls-permissive.yaml
$ cat file.yaml
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
@@ -51,7 +51,7 @@ Examples:
tls:
mode: ISTIO_MUTUAL
$ cat istio-mtls-permissive.yaml | jc --yaml -p
$ cat file.yaml | jc --yaml -p
[
{
"apiVersion": "authentication.istio.io/v1alpha1",

View File

@@ -99,4 +99,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin
Version 1.1 by Matt J (https://github.com/listuser)
Version 1.2 by Matt J (https://github.com/listuser)

View File

@@ -19,7 +19,7 @@ jc - JSON Convert streaming utils
### streaming\_input\_type\_check
```python
def streaming_input_type_check(data: Iterable) -> None
def streaming_input_type_check(data: Iterable[Union[str, bytes]]) -> None
```
Ensure input data is an iterable, but not a string or bytes. Raises
@@ -40,7 +40,8 @@ Ensure each line is a string. Raises `TypeError` if not.
### stream\_success
```python
def stream_success(output_line: Dict, ignore_exceptions: bool) -> Dict
def stream_success(output_line: JSONDictType,
ignore_exceptions: bool) -> JSONDictType
```
Add `_jc_meta` object to output line if `ignore_exceptions=True`
@@ -50,7 +51,7 @@ Add `_jc_meta` object to output line if `ignore_exceptions=True`
### stream\_error
```python
def stream_error(e: BaseException, line: str) -> Dict
def stream_error(e: BaseException, line: str) -> JSONDictType
```
Return an error `_jc_meta` field.
@@ -60,7 +61,7 @@ Return an error `_jc_meta` field.
### add\_jc\_meta
```python
def add_jc_meta(func)
def add_jc_meta(func: F) -> F
```
Decorator for streaming parsers to add stream_success and stream_error
@@ -106,7 +107,7 @@ In all cases above:
```python
def raise_or_yield(ignore_exceptions: bool, e: BaseException,
line: str) -> tuple
line: str) -> Tuple[BaseException, str]
```
Return the exception object and line string if ignore_exceptions is

View File

@@ -64,7 +64,7 @@ Returns:
### is\_compatible
```python
def is_compatible(compatible: List) -> bool
def is_compatible(compatible: List[str]) -> bool
```
Returns True if the parser is compatible with the running OS platform.
@@ -75,7 +75,7 @@ Returns True if the parser is compatible with the running OS platform.
```python
def compatibility(mod_name: str,
compatible: List,
compatible: List[str],
quiet: bool = False) -> None
```
@@ -91,7 +91,7 @@ Parameters:
the parser. compatible options:
linux, darwin, cygwin, win32, aix, freebsd
quiet: (bool) supress compatibility message if True
quiet: (bool) suppress compatibility message if True
Returns:
@@ -125,7 +125,7 @@ Returns:
### convert\_to\_int
```python
def convert_to_int(value: Union[str, float]) -> Optional[int]
def convert_to_int(value: object) -> Optional[int]
```
Converts string and float input to int. Strips all non-numeric
@@ -144,7 +144,7 @@ Returns:
### convert\_to\_float
```python
def convert_to_float(value: Union[str, int]) -> Optional[float]
def convert_to_float(value: object) -> Optional[float]
```
Converts string and int input to float. Strips all non-numeric
@@ -163,7 +163,7 @@ Returns:
### convert\_to\_bool
```python
def convert_to_bool(value: Union[str, int, float]) -> bool
def convert_to_bool(value: object) -> bool
```
Converts string, integer, or float input to boolean by checking
@@ -183,7 +183,7 @@ Returns:
### input\_type\_check
```python
def input_type_check(data: str) -> None
def input_type_check(data: object) -> None
```
Ensure input data is a string. Raises `TypeError` if not.
@@ -201,8 +201,8 @@ class timestamp()
### \_\_init\_\_
```python
def __init__(datetime_string: str,
format_hint: Optional[Iterable] = None) -> None
def __init__(datetime_string: Optional[str],
format_hint: Optional[Iterable[int]] = None) -> None
```
Input a datetime text string of several formats and convert to a
@@ -233,3 +233,6 @@ Returns a timestamp object with the following attributes:
utc (int | None): aware timestamp only if UTC timezone
detected in datetime string. None if conversion fails.
iso (str | None): ISO string - timezone information is output
only if UTC timezone is detected in the datetime string.

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# type: ignore
# Copyright (c) 2005-2010 ActiveState Software Inc.
# Copyright (c) 2013 Eddy Petrișor

1339
jc/cli.py

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@ from typing import List, Dict
long_options_map: Dict[str, List[str]] = {
'--about': ['a', 'about jc'],
'--force-color': ['C', 'force color output even when using pipes (overrides -m)'],
'--force-color': ['C', 'force color output (overrides -m)'],
'--debug': ['d', 'debug (double for verbose debug)'],
'--help': ['h', 'help (--help --parser_name for parser documentation)'],
'--monochrome': ['m', 'monochrome output'],
@@ -18,7 +18,7 @@ long_options_map: Dict[str, List[str]] = {
'--zsh-comp': ['Z', 'gen Zsh completion: jc -Z > "${fpath[1]}/_jc"']
}
new_pygments_colors = {
new_pygments_colors: Dict[str, str] = {
'black': 'ansiblack',
'red': 'ansired',
'green': 'ansigreen',
@@ -37,7 +37,7 @@ new_pygments_colors = {
'white': 'ansiwhite',
}
old_pygments_colors = {
old_pygments_colors: Dict[str, str] = {
'black': '#ansiblack',
'red': '#ansidarkred',
'green': '#ansidarkgreen',
@@ -55,3 +55,43 @@ old_pygments_colors = {
'brightcyan': '#ansiturquoise',
'white': '#ansiwhite',
}
helptext_preamble_string: str = f'''\
jc converts the output of many commands, file-types, and strings to JSON or YAML
Usage:
Standard syntax:
COMMAND | jc [OPTIONS] PARSER
cat FILE | jc [OPTIONS] PARSER
echo STRING | jc [OPTIONS] PARSER
Magic syntax:
jc [OPTIONS] COMMAND
jc [OPTIONS] /proc/<path-to-procfile>
Parsers:
'''
helptext_end_string: str = '''\
Examples:
Standard Syntax:
$ dig www.google.com | jc --pretty --dig
$ cat /proc/meminfo | jc --pretty --proc
Magic Syntax:
$ jc --pretty dig www.google.com
$ jc --pretty /proc/meminfo
Parser Documentation:
$ jc --help --dig
More Help:
$ jc -hh # show hidden parsers
$ jc -hhh # list parsers by category tags
'''

52
jc/jc_types.py Normal file
View File

@@ -0,0 +1,52 @@
"""jc - JSON Convert lib module"""
import sys
from typing import Any, Dict, List, Tuple, Iterator, Optional, Union
JSONDictType = Dict[str, Any]
StreamingOutputType = Iterator[Union[JSONDictType, Tuple[BaseException, str]]]
if sys.version_info >= (3, 8):
from typing import TypedDict
ParserInfoType = TypedDict(
'ParserInfoType',
{
"name": str,
"argument": str,
"version": str,
"description": str,
"author": str,
"author_email": str,
"compatible": List[str],
"magic_commands": List[str],
"tags": List[str],
"documentation": str,
"streaming": bool,
"plugin": bool,
"hidden": bool,
"deprecated": bool
},
total=False
)
TimeStampFormatType = TypedDict(
'TimeStampFormatType',
{
'id': int,
'format': str,
'locale': Optional[str]
}
)
else:
ParserInfoType = Dict
TimeStampFormatType = Dict
try:
from pygments.token import (Name, Number, String, Keyword)
CustomColorType = Dict[Union[Name.Tag, Number, String, Keyword], str]
except Exception:
CustomColorType = Dict # type: ignore

243
jc/lib.py
View File

@@ -3,12 +3,15 @@ import sys
import os
import re
import importlib
from typing import Dict, List, Iterable, Union, Iterator
from typing import List, Iterable, Union, Iterator
from types import ModuleType
from .jc_types import ParserInfoType, JSONDictType
from jc import appdirs
__version__ = '1.22.0'
parsers = [
__version__ = '1.22.5'
parsers: List[str] = [
'acpi',
'airport',
'airport-s',
@@ -16,15 +19,19 @@ parsers = [
'asciitable',
'asciitable-m',
'blkid',
'cbt',
'cef',
'cef-s',
'chage',
'cksum',
'clf',
'clf-s',
'crontab',
'crontab-u',
'csv',
'csv-s',
'date',
'datetime-iso',
'df',
'dig',
'dir',
@@ -34,11 +41,13 @@ parsers = [
'email-address',
'env',
'file',
'findmnt',
'finger',
'free',
'fstab',
'git-log',
'git-log-s',
'git-ls-remote',
'gpg',
'group',
'gshadow',
@@ -50,12 +59,14 @@ parsers = [
'id',
'ifconfig',
'ini',
'ini-dup',
'iostat',
'iostat-s',
'ip-address',
'iptables',
'iso-datetime',
'iw-scan',
'iwconfig',
'jar-manifest',
'jobs',
'jwt',
@@ -66,6 +77,7 @@ parsers = [
'lsblk',
'lsmod',
'lsof',
'lspci',
'lsusb',
'm3u',
'mdadm',
@@ -75,7 +87,11 @@ parsers = [
'netstat',
'nmcli',
'ntpq',
'openvpn',
'os-prober',
'passwd',
'pci-ids',
'pgpass',
'pidstat',
'pidstat-s',
'ping',
@@ -139,9 +155,11 @@ parsers = [
'rpm-qi',
'rsync',
'rsync-s',
'semver',
'sfdisk',
'shadow',
'ss',
'sshd-conf',
'stat',
'stat-s',
'sysctl',
@@ -157,10 +175,12 @@ parsers = [
'time',
'timedatectl',
'timestamp',
'toml',
'top',
'top-s',
'tracepath',
'traceroute',
'udevadm',
'ufw',
'ufw-appinfo',
'uname',
@@ -181,19 +201,19 @@ parsers = [
'zipinfo'
]
def _cliname_to_modname(parser_cli_name):
def _cliname_to_modname(parser_cli_name: str) -> str:
"""Return real module name (dashes converted to underscores)"""
return parser_cli_name.replace('--', '').replace('-', '_')
def _modname_to_cliname(parser_mod_name):
def _modname_to_cliname(parser_mod_name: str) -> str:
"""Return module's cli name (underscores converted to dashes)"""
return parser_mod_name.replace('_', '-')
# Create the local_parsers list. This is a list of custom or
# override parsers from <user_data_dir>/jc/jcparsers/*.py.
# Once this list is created, extend the parsers list with it.
local_parsers = []
data_dir = appdirs.user_data_dir('jc', 'jc')
local_parsers: List[str] = []
data_dir = appdirs.user_data_dir('jc', 'jc') # type: ignore
local_parsers_dir = os.path.join(data_dir, 'jcparsers')
if os.path.isdir(local_parsers_dir):
sys.path.append(data_dir)
@@ -208,21 +228,20 @@ if os.path.isdir(local_parsers_dir):
except Exception:
pass
def _parser_argument(parser_mod_name):
def _parser_argument(parser_mod_name: str) -> str:
"""Return short name of the parser with dashes and with -- prefix"""
parser = _modname_to_cliname(parser_mod_name)
return f'--{parser}'
def _get_parser(parser_mod_name):
def _get_parser(parser_mod_name: str) -> ModuleType:
"""Return the parser module object"""
# ensure parser_mod_name is a true module name and not a cli name
parser_mod_name = _cliname_to_modname(parser_mod_name)
parser_cli_name = _modname_to_cliname(parser_mod_name)
modpath = 'jcparsers.' if parser_cli_name in local_parsers else 'jc.parsers.'
modpath: str = 'jcparsers.' if parser_cli_name in local_parsers else 'jc.parsers.'
return importlib.import_module(f'{modpath}{parser_mod_name}')
def _parser_is_streaming(parser):
def _parser_is_streaming(parser: ModuleType) -> bool:
"""
Returns True if this is a streaming parser, else False
@@ -233,16 +252,39 @@ def _parser_is_streaming(parser):
return False
def _parser_is_hidden(parser: ModuleType) -> bool:
"""
Returns True if this is a hidden parser, else False
parser is a parser module object.
"""
if getattr(parser.info, 'hidden', None):
return True
return False
def _parser_is_deprecated(parser: ModuleType) -> bool:
"""
Returns True if this is a deprecated parser, else False
parser is a parser module object.
"""
if getattr(parser.info, 'deprecated', None):
return True
return False
def parse(
parser_mod_name: str,
parser_mod_name: Union[str, ModuleType],
data: Union[str, bytes, Iterable[str]],
quiet: bool = False,
raw: bool = False,
ignore_exceptions: bool = None,
**kwargs
) -> Union[Dict, List[Dict], Iterator[Dict]]:
) -> Union[JSONDictType, List[JSONDictType], Iterator[JSONDictType]]:
"""
Parse the string data using the supplied parser module.
Parse the data (string or bytes) using the supplied parser (string or
module object).
This function provides a high-level API to simplify parser use. This
function will call built-in parsers and custom plugin parsers.
@@ -266,6 +308,14 @@ def parse(
To get a list of available parser module names, use `parser_mod_list()`.
Alternatively, a parser module object can be supplied:
>>> import jc
>>> import jc.parsers.date as jc_date
>>> date_obj = jc.parse(jc_date, 'Tue Jan 18 10:23:07 PST 2022')
>>> print(f'The year is: {date_obj["year"]}')
The year is: 2022
You can also use the lower-level parser modules directly:
>>> import jc.parsers.date
@@ -286,11 +336,14 @@ def parse(
Parameters:
parser_mod_name: (string) name of the parser module. This
function will accept module_name,
parser_mod_name: (string or name of the parser module. This
Module) function will accept module_name,
cli-name, and --argument-name
variants of the module name.
A Module object can also be passed
directly or via _get_parser()
data: (string or data to parse (string or bytes for
bytes or standard parsers, iterable of
iterable) strings for streaming parsers)
@@ -307,67 +360,138 @@ def parse(
Standard Parsers: Dictionary or List of Dictionaries
Streaming Parsers: Generator Object containing Dictionaries
"""
jc_parser = _get_parser(parser_mod_name)
if isinstance(parser_mod_name, ModuleType):
jc_parser = parser_mod_name
else:
jc_parser = _get_parser(parser_mod_name)
if ignore_exceptions is not None:
return jc_parser.parse(data, quiet=quiet, raw=raw,
ignore_exceptions=ignore_exceptions, **kwargs)
return jc_parser.parse(
data,
quiet=quiet,
raw=raw,
ignore_exceptions=ignore_exceptions,
**kwargs
)
return jc_parser.parse(data, quiet=quiet, raw=raw, **kwargs)
def parser_mod_list() -> List[str]:
def parser_mod_list(
show_hidden: bool = False,
show_deprecated: bool = False
) -> List[str]:
"""Returns a list of all available parser module names."""
return [_cliname_to_modname(p) for p in parsers]
plist: List[str] = []
for p in parsers:
parser = _get_parser(p)
def plugin_parser_mod_list() -> List[str]:
if not show_hidden and _parser_is_hidden(parser):
continue
if not show_deprecated and _parser_is_deprecated(parser):
continue
plist.append(_cliname_to_modname(p))
return plist
def plugin_parser_mod_list(
show_hidden: bool = False,
show_deprecated: bool = False
) -> List[str]:
"""
Returns a list of plugin parser module names. This function is a
subset of `parser_mod_list()`.
"""
return [_cliname_to_modname(p) for p in local_parsers]
plist: List[str] = []
for p in local_parsers:
parser = _get_parser(p)
def standard_parser_mod_list() -> List[str]:
if not show_hidden and _parser_is_hidden(parser):
continue
if not show_deprecated and _parser_is_deprecated(parser):
continue
plist.append(_cliname_to_modname(p))
return plist
def standard_parser_mod_list(
show_hidden: bool = False,
show_deprecated: bool = False
) -> List[str]:
"""
Returns a list of standard parser module names. This function is a
subset of `parser_mod_list()` and does not contain any streaming
parsers.
"""
plist = []
plist: List[str] = []
for p in parsers:
parser = _get_parser(p)
if not _parser_is_streaming(parser):
if not show_hidden and _parser_is_hidden(parser):
continue
if not show_deprecated and _parser_is_deprecated(parser):
continue
plist.append(_cliname_to_modname(p))
return plist
def streaming_parser_mod_list() -> List[str]:
def streaming_parser_mod_list(
show_hidden: bool = False,
show_deprecated: bool = False
) -> List[str]:
"""
Returns a list of streaming parser module names. This function is a
subset of `parser_mod_list()`.
"""
plist = []
plist: List[str] = []
for p in parsers:
parser = _get_parser(p)
if _parser_is_streaming(parser):
if not show_hidden and _parser_is_hidden(parser):
continue
if not show_deprecated and _parser_is_deprecated(parser):
continue
plist.append(_cliname_to_modname(p))
return plist
def parser_info(parser_mod_name: str, documentation: bool = False) -> Dict:
def parser_info(
parser_mod_name: Union[str, ModuleType],
documentation: bool = False
) -> ParserInfoType:
"""
Returns a dictionary that includes the parser module metadata.
Parameters:
parser_mod_name: (string) name of the parser module. This
function will accept module_name,
parser_mod_name: (string or name of the parser module. This
Module) function will accept module_name,
cli-name, and --argument-name
variants of the module name.
variants of the module name as well
as a parser module object.
documentation: (boolean) include parser docstring if True
"""
# ensure parser_mod_name is a true module name and not a cli name
parser_mod_name = _cliname_to_modname(parser_mod_name)
parser_mod = _get_parser(parser_mod_name)
info_dict: Dict = {}
if isinstance(parser_mod_name, ModuleType):
parser_mod = parser_mod_name
parser_mod_name = parser_mod.__name__.split('.')[-1]
else:
# ensure parser_mod_name is a true module name and not a cli name
parser_mod_name = _cliname_to_modname(parser_mod_name)
parser_mod = _get_parser(parser_mod_name)
info_dict: ParserInfoType = {}
if hasattr(parser_mod, 'info'):
info_dict['name'] = parser_mod_name
@@ -376,7 +500,7 @@ def parser_info(parser_mod_name: str, documentation: bool = False) -> Dict:
for k, v in parser_entry.items():
if not k.startswith('__'):
info_dict[k] = v
info_dict[k] = v # type: ignore
if _modname_to_cliname(parser_mod_name) in local_parsers:
info_dict['plugin'] = True
@@ -389,38 +513,51 @@ def parser_info(parser_mod_name: str, documentation: bool = False) -> Dict:
return info_dict
def all_parser_info(documentation: bool = False,
show_hidden: bool = False
) -> List[Dict]:
def all_parser_info(
documentation: bool = False,
show_hidden: bool = False,
show_deprecated: bool = False
) -> List[ParserInfoType]:
"""
Returns a list of dictionaries that includes metadata for all parser
modules.
modules. By default only non-hidden, non-deprecated parsers are
returned.
Parameters:
documentation: (boolean) include parser docstrings if True
show_hidden: (boolean) also show parsers marked as hidden
in their info metadata.
show_deprecated: (boolean) also show parsers marked as
deprecated in their info metadata.
"""
temp_list = [parser_info(p, documentation=documentation) for p in parsers]
plist: List[str] = []
for p in parsers:
parser = _get_parser(p)
p_list = []
if show_hidden:
p_list = temp_list
if not show_hidden and _parser_is_hidden(parser):
continue
else:
for item in temp_list:
if not item.get('hidden', None):
p_list.append(item)
if not show_deprecated and _parser_is_deprecated(parser):
continue
return p_list
plist.append(_cliname_to_modname(p))
p_info_list: List[ParserInfoType] = [parser_info(p, documentation=documentation) for p in plist]
def get_help(parser_mod_name: str) -> None:
return p_info_list
def get_help(parser_mod_name: Union[str, ModuleType]) -> None:
"""
Show help screen for the selected parser.
This function will accept **module_name**, **cli-name**, and
**--argument-name** variants of the module name string.
**--argument-name** variants of the module name string as well as a
parser module object.
"""
help(_get_parser(parser_mod_name))
if isinstance(parser_mod_name, ModuleType):
jc_parser = parser_mod_name
else:
jc_parser = _get_parser(parser_mod_name)
help(jc_parser)

View File

@@ -233,6 +233,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['acpi']
tags = ['command']
__version__ = info.version

View File

@@ -86,6 +86,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['darwin']
magic_commands = ['airport -I']
tags = ['command']
__version__ = info.version

View File

@@ -115,6 +115,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['darwin']
magic_commands = ['airport -s']
tags = ['command']
__version__ = info.version

View File

@@ -119,12 +119,13 @@ import jc.parsers.universal
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.11'
version = '1.12'
description = '`arp` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['arp']
tags = ['command']
__version__ = info.version
@@ -221,14 +222,26 @@ def parse(
else:
for line in cleandata:
splitline = line.split()
if '<incomplete>' not in splitline:
# Ignore AIX bucket information
if 'bucket:' in splitline[0]:
continue
elif 'There' in splitline[0] and 'are' in splitline[1]:
continue
# AIX uses (incomplete)
elif '<incomplete>' not in splitline and '(incomplete)' not in splitline:
output_line = {
'name': splitline[0],
'address': splitline[1].lstrip('(').rstrip(')'),
'hwtype': splitline[4].lstrip('[').rstrip(']'),
'hwaddress': splitline[3],
'iface': splitline[6],
}
# Handle permanence and ignore interface in AIX
if 'permanent' in splitline:
output_line['permanent'] = True
elif 'in' not in splitline[6]: # AIX doesn't show interface
output_line['iface'] = splitline[6]
else:
output_line = {
@@ -236,8 +249,10 @@ def parse(
'address': splitline[1].lstrip('(').rstrip(')'),
'hwtype': None,
'hwaddress': None,
'iface': splitline[5],
}
# AIX doesn't show interface
if len(splitline) >= 5:
output_line['iface'] = splitline[5]
raw_output.append(output_line)

View File

@@ -130,6 +130,7 @@ class info():
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['generic', 'string']
__version__ = info.version

View File

@@ -115,6 +115,7 @@ class info():
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['generic', 'string']
__version__ = info.version

View File

@@ -567,7 +567,7 @@ class DSASignature(Sequence):
@classmethod
def from_p1363(cls, data):
"""
Reads a signature from a byte string encoding accordint to IEEE P1363,
Reads a signature from a byte string encoding according to IEEE P1363,
which is used by Microsoft's BCryptSignHash() function.
:param data:

View File

@@ -247,7 +247,7 @@ class Asn1Value(object):
:param no_explicit:
If explicit tagging info should be removed from this instance.
Used internally to allow contructing the underlying value that
Used internally to allow constructing the underlying value that
has been wrapped in an explicit tag.
:param tag_type:
@@ -697,7 +697,7 @@ class Castable(object):
if other_class.tag != self.__class__.tag:
raise TypeError(unwrap(
'''
Can not covert a value from %s object to %s object since they
Can not convert a value from %s object to %s object since they
use different tags: %d versus %d
''',
type_name(other_class),
@@ -1349,7 +1349,7 @@ class Choice(Asn1Value):
class Concat(object):
"""
A class that contains two or more encoded child values concatentated
A class that contains two or more encoded child values concatenated
together. THIS IS NOT PART OF THE ASN.1 SPECIFICATION! This exists to handle
the x509.TrustedCertificate() class for OpenSSL certificates containing
extra information.
@@ -3757,7 +3757,7 @@ class Sequence(Asn1Value):
def _make_value(self, field_name, field_spec, value_spec, field_params, value):
"""
Contructs an appropriate Asn1Value object for a field
Constructs an appropriate Asn1Value object for a field
:param field_name:
A unicode string of the field name
@@ -3766,7 +3766,7 @@ class Sequence(Asn1Value):
An Asn1Value class that is the field spec
:param value_spec:
An Asn1Value class that is the vaue spec
An Asn1Value class that is the value spec
:param field_params:
None or a dict of params for the field spec

View File

@@ -127,6 +127,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['blkid']
tags = ['command']
__version__ = info.version

195
jc/parsers/cbt.py Normal file
View File

@@ -0,0 +1,195 @@
"""jc - JSON Convert `cbt` command output parser (Google Bigtable)
Parses the human-, but not machine-, friendly output of the cbt command (for
Google's Bigtable).
No effort is made to convert the data types of the values in the cells.
The `timestamp_epoch` calculated timestamp field is naive. (i.e. based on
the local time of the system the parser is run on)
The `timestamp_epoch_utc` calculated timestamp field is timezone-aware and
is only available if the timestamp has a UTC timezone.
The `timestamp_iso` calculated timestamp field will only include UTC
timezone information if the timestamp has a UTC timezone.
Raw output contains all cells for each column (including timestamps), while
the normal output contains only the latest value for each column.
Usage (cli):
$ cbt | jc --cbt
or
$ jc cbt
Usage (module):
import jc
result = jc.parse('cbt', cbt_command_output)
Schema:
[
{
"key": string,
"cells": {
<string>: { # column family
<string>: string # column: value
}
}
}
]
Schema (raw):
[
{
"key": string,
"cells": [
{
"column_family": string,
"column": string,
"value": string,
"timestamp_iso": string,
"timestamp_epoch": integer,
"timestamp_epoch_utc": integer
}
]
}
]
Examples:
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p
[
{
"key": "foo",
"cells": {
"foo": {
"bar": "baz"
}
}
}
]
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p -r
[
{
"key": "foo",
"cells": [
{
"column_family": "foo",
"column": "bar",
"value": "baz1",
"timestamp_iso": "1970-01-01T01:00:00",
"timestamp_epoch": 32400,
"timestamp_epoch_utc": null
}
]
}
]
"""
from itertools import groupby
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`cbt` (Google Bigtable) command parser'
author = 'Andreas Weiden'
author_email = 'andreas.weiden@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['cbt']
tags = ['command']
__version__ = info.version
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
out_data = []
for row in proc_data:
cells: Dict = {}
key_func = lambda cell: (cell["column_family"], cell["column"])
all_cells = sorted(row["cells"], key=key_func)
for (column_family, column), group in groupby(all_cells, key=key_func):
group_list = sorted(group, key=lambda cell: cell["timestamp_iso"], reverse=True)
if column_family not in cells:
cells[column_family] = {}
cells[column_family][column] = group_list[0]["value"]
row["cells"] = cells
out_data.append(row)
return out_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[JSONDictType]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List[Dict] = []
if jc.utils.has_data(data):
for line in filter(None, data.split("-" * 40)):
key = None
cells = []
column_name = ""
timestamp = ""
value_next = False
for field in line.splitlines():
if not field.strip():
continue
if field.startswith(" " * 4):
value = field.strip(' "')
if value_next:
dt = jc.utils.timestamp(timestamp, format_hint=(1750, 1755))
cells.append({
"column_family": column_name.split(":", 1)[0],
"column": column_name.split(":", 1)[1],
"value": value,
"timestamp_iso": dt.iso,
"timestamp_epoch": dt.naive,
"timestamp_epoch_utc": dt.utc
})
elif field.startswith(" " * 2):
column_name, timestamp = map(str.strip, field.split("@"))
value_next = True
else:
key = field
if key is not None:
raw_output.append({"key": key, "cells": cells})
return raw_output if raw else _process(raw_output)

View File

@@ -129,6 +129,8 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the pycef library at https://github.com/DavidJBianco/pycef/releases/tag/v1.11-2'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
__version__ = info.version
@@ -185,7 +187,7 @@ def _pycef_parse(str_input):
# If the input entry had any blanks in the required headers, that's wrong
# and we should return. Note we explicitly don't check the last item in the
# split list becuase the header ends in a '|' which means the last item
# split list because the header ends in a '|' which means the last item
# will always be an empty string (it doesn't exist, but the delimiter does).
if "" in spl[0:-1]:
raise ParseError('Blank field(s) in CEF header. Is it valid CEF format?')

View File

@@ -103,6 +103,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the pycef library at https://github.com/DavidJBianco/pycef/releases/tag/v1.11-2'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
streaming = True

View File

@@ -63,6 +63,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['chage --list', 'chage -l']
tags = ['command']
__version__ = info.version

View File

@@ -60,6 +60,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['cksum', 'sum']
tags = ['command']
__version__ = info.version

299
jc/parsers/clf.py Normal file
View File

@@ -0,0 +1,299 @@
"""jc - JSON Convert Common Log Format file parser
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf
Usage (module):
import jc
result = jc.parse('clf', common_log_file_output)
Schema:
Empty strings and `-` values are converted to `null`/`None`.
[
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
]
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf -p
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": 10,
"month": "Oct",
"year": 2000,
"hour": 13,
"minute": 55,
"second": 36,
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": 200,
"bytes": 2326,
"referer": null,
"user_agent": null,
"extra": null,
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0",
"epoch": 971211336,
"epoch_utc": null
},
{
"host": "1.1.1.2",
"ident": null,
"authuser": null,
"date": "11/Nov/2016:03:04:55 +0100",
"day": 11,
"month": "Nov",
"year": 2016,
"hour": 3,
"minute": 4,
"second": 55,
"tz": "+0100",
"request": "GET /",
"status": 200,
"bytes": 83,
"referer": null,
"user_agent": null,
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null,
"epoch": 1478862295,
"epoch_utc": null
},
...
]
$ cat file.log | jc --clf -p -r
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": "10",
"month": "Oct",
"year": "2000",
"hour": "13",
"minute": "55",
"second": "36",
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": "200",
"bytes": "2326",
"referer": null,
"user_agent": null,
"extra": "",
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0"
},
{
"host": "1.1.1.2",
"ident": "-",
"authuser": "-",
"date": "11/Nov/2016:03:04:55 +0100",
"day": "11",
"month": "Nov",
"year": "2016",
"hour": "03",
"minute": "04",
"second": "55",
"tz": "+0100",
"request": "GET /",
"status": "200",
"bytes": "83",
"referer": "-",
"user_agent": "-",
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null
},
...
]
"""
import re
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'Common and Combined Log Format file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
__version__ = info.version
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
int_list = {'day', 'year', 'hour', 'minute', 'second', 'status', 'bytes'}
for log in proc_data:
for key, val in log.items():
# integer conversions
if key in int_list:
log[key] = jc.utils.convert_to_int(val)
# convert `-` and blank values to None
if val == '-' or val == '':
log[key] = None
# add unix timestamps
if 'date' in log:
ts = jc.utils.timestamp(log['date'], format_hint=(1800,))
log['epoch'] = ts.naive
log['epoch_utc'] = ts.utc
return proc_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[JSONDictType]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List[Dict] = []
output_line: Dict = {}
clf_pattern = re.compile(r'''
^(?P<host>-|\S+)\s
(?P<ident>-|\S+)\s
(?P<authuser>-|\S+)\s
\[
(?P<date>
(?P<day>\d+)/
(?P<month>\S\S\S)/
(?P<year>\d\d\d\d):
(?P<hour>\d\d):
(?P<minute>\d\d):
(?P<second>\d\d)\s
(?P<tz>\S+)
)
\]\s
\"(?P<request>.*?)\"\s
(?P<status>-|\d\d\d)\s
(?P<bytes>-|\d+)\s?
(?:\"(?P<referer>.*?)\"\s?)?
(?:\"(?P<user_agent>.*?)\"\s?)?
(?P<extra>.*)
''', re.VERBOSE
)
request_pattern = re.compile(r'''
(?P<request_method>\S+)\s
(?P<request_url>.*?(?=\sHTTPS?/|$))\s? # positive lookahead for HTTP(S)/ or end of string
(?P<request_version>HTTPS?/[\d\.]+)?
''', re.VERBOSE
)
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
output_line = {}
clf_match = re.match(clf_pattern, line)
if clf_match:
output_line = clf_match.groupdict()
if output_line.get('request', None):
request_string = output_line['request']
request_match = re.match(request_pattern, request_string)
if request_match:
output_line.update(request_match.groupdict())
raw_output.append(output_line)
else:
raw_output.append(
{"unparsable": line}
)
return raw_output if raw else _process(raw_output)

224
jc/parsers/clf_s.py Normal file
View File

@@ -0,0 +1,224 @@
"""jc - JSON Convert Common Log Format file streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf-s
Usage (module):
import jc
result = jc.parse('clf_s', common_log_file_output.splitlines())
for item in result:
# do something
Schema:
Empty strings and `-` values are converted to `null`/`None`.
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf-s
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":null,"authuser":null,"date":"11/Nov/2016...}
...
$ cat file.log | jc --clf-s -r
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":"-","authuser":"-","date":"11/Nov/2016:0...}
...
"""
import re
from typing import Dict, Iterable
import jc.utils
from jc.streaming import (
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
)
from jc.jc_types import JSONDictType, StreamingOutputType
from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'Common and Combined Log Format file streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
streaming = True
__version__ = info.version
def _process(proc_data: JSONDictType) -> JSONDictType:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (Dictionary) raw structured data to process
Returns:
Dictionary. Structured data to conform to the schema.
"""
int_list = {'day', 'year', 'hour', 'minute', 'second', 'status', 'bytes'}
for key, val in proc_data.items():
# integer conversions
if key in int_list:
proc_data[key] = jc.utils.convert_to_int(val)
# convert `-` and blank values to None
if val == '-' or val == '':
proc_data[key] = None
# add unix timestamps
if 'date' in proc_data:
ts = jc.utils.timestamp(proc_data['date'], format_hint=(1800,))
proc_data['epoch'] = ts.naive
proc_data['epoch_utc'] = ts.utc
return proc_data
@add_jc_meta
def parse(
data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False
) -> StreamingOutputType:
"""
Main text parsing generator function. Returns an iterable object.
Parameters:
data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Returns:
Iterable of Dictionaries
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
streaming_input_type_check(data)
clf_pattern = re.compile(r'''
^(?P<host>-|\S+)\s
(?P<ident>-|\S+)\s
(?P<authuser>-|\S+)\s
\[
(?P<date>
(?P<day>\d+)/
(?P<month>\S\S\S)/
(?P<year>\d\d\d\d):
(?P<hour>\d\d):
(?P<minute>\d\d):
(?P<second>\d\d)\s
(?P<tz>\S+)
)
\]\s
\"(?P<request>.*?)\"\s
(?P<status>-|\d\d\d)\s
(?P<bytes>-|\d+)\s?
(?:\"(?P<referer>.*?)\"\s?)?
(?:\"(?P<user_agent>.*?)\"\s?)?
(?P<extra>.*)
''', re.VERBOSE
)
request_pattern = re.compile(r'''
(?P<request_method>\S+)\s
(?P<request_url>.*?(?=\sHTTPS?/|$))\s? # positive lookahead for HTTP(S)/ or end of string
(?P<request_version>HTTPS?/[\d\.]+)?
''', re.VERBOSE
)
for line in data:
try:
streaming_line_input_type_check(line)
output_line: Dict = {}
if not line.strip():
continue
clf_match = re.match(clf_pattern, line)
if clf_match:
output_line = clf_match.groupdict()
if output_line.get('request', None):
request_string = output_line['request']
request_match = re.match(request_pattern, request_string)
if request_match:
output_line.update(request_match.groupdict())
else:
output_line = {"unparsable": line.strip()}
if output_line:
yield output_line if raw else _process(output_line)
else:
raise ParseError('Not Common Log Format data')
except Exception as e:
yield raise_or_yield(ignore_exceptions, e, line)

View File

@@ -180,6 +180,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['crontab']
tags = ['file', 'command']
__version__ = info.version

View File

@@ -176,6 +176,7 @@ class info():
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'aix', 'freebsd']
tags = ['file', 'command']
__version__ = info.version

View File

@@ -72,24 +72,27 @@ Examples:
...
]
"""
from typing import List, Union, Type
from jc.jc_types import JSONDictType
import jc.utils
import csv
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.4'
version = '1.5'
description = 'CSV file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the python standard csv library'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
__version__ = info.version
def _process(proc_data):
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
Final processing to conform to the schema.
@@ -107,7 +110,11 @@ def _process(proc_data):
return proc_data
def parse(data, raw=False, quiet=False):
def parse(
data: Union[str, bytes],
raw: bool = False,
quiet: bool = False
) -> List[JSONDictType]:
"""
Main text parsing function
@@ -124,6 +131,12 @@ def parse(data, raw=False, quiet=False):
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
# remove BOM bytes, if present
if isinstance(data, str):
data = data.encode('utf-8')
data = data.decode('utf-8-sig')
raw_output = []
cleandata = data.splitlines()
@@ -132,7 +145,7 @@ def parse(data, raw=False, quiet=False):
if jc.utils.has_data(data):
dialect = 'excel' # default in csv module
dialect: Union[str, Type[csv.Dialect]] = 'excel' # default in csv module
try:
dialect = csv.Sniffer().sniff(data[:1024])
if '""' in data:
@@ -145,7 +158,4 @@ def parse(data, raw=False, quiet=False):
for row in reader:
raw_output.append(row)
if raw:
return raw_output
else:
return _process(raw_output)
return raw_output if raw else _process(raw_output)

View File

@@ -63,12 +63,13 @@ from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.3'
version = '1.4'
description = 'CSV file streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the python standard csv library'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
streaming = True
@@ -127,7 +128,14 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
if len(temp_list) == 1:
raise ParseError('Unable to detect line endings. Please try the non-streaming CSV parser instead.')
sniffdata = '\n'.join(temp_list)[:1024]
# remove BOM bytes from first row, if present
if temp_list:
if isinstance(temp_list[0], str):
temp_list[0] = temp_list[0].encode('utf-8')
temp_list[0] = temp_list[0].decode('utf-8-sig')
sniffdata = '\r\n'.join(temp_list)[:1024]
dialect = 'excel' # default in csv module
try:

View File

@@ -84,6 +84,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['date']
tags = ['command']
__version__ = info.version

314
jc/parsers/datetime_iso.py Normal file
View File

@@ -0,0 +1,314 @@
"""jc - JSON Convert ISO 8601 Datetime string parser
This parser supports standard ISO 8601 strings that include both date and
time. If no timezone or offset information is available in the string, then
UTC timezone is used.
Usage (cli):
$ echo "2022-07-20T14:52:45Z" | jc --iso-datetime
Usage (module):
import jc
result = jc.parse('iso_datetime', iso_8601_string)
Schema:
{
"year": integer,
"month": string,
"month_num": integer,
"day": integer,
"weekday": string,
"weekday_num": integer,
"hour": integer,
"hour_24": integer,
"minute": integer,
"second": integer,
"microsecond": integer,
"period": string,
"utc_offset": string,
"day_of_year": integer,
"week_of_year": integer,
"iso": string,
"timestamp": integer # [0]
}
[0] timezone aware UNIX timestamp expressed in UTC
Examples:
$ echo "2022-07-20T14:52:45Z" | jc --iso-datetime -p
{
"year": 2022,
"month": "Jul",
"month_num": 7,
"day": 20,
"weekday": "Wed",
"weekday_num": 3,
"hour": 2,
"hour_24": 14,
"minute": 52,
"second": 45,
"microsecond": 0,
"period": "PM",
"utc_offset": "+0000",
"day_of_year": 201,
"week_of_year": 29,
"iso": "2022-07-20T14:52:45+00:00",
"timestamp": 1658328765
}
"""
import datetime
import re
import typing
from decimal import Decimal
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'ISO 8601 Datetime string parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the pyiso8601 library from https://github.com/micktwomey/pyiso8601/releases/tag/1.0.2'
compatible = ['linux', 'aix', 'freebsd', 'darwin', 'win32', 'cygwin']
tags = ['standard', 'string']
__version__ = info.version
####################################################
"""
pyiso8601 library from https://github.com/micktwomey/pyiso8601/releases/tag/1.0.2
"""
"""
Copyright (c) 2007 - 2022 Michael Twomey
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
"""ISO 8601 date time string parsing
Basic usage:
>>> import iso8601
>>> iso8601._parse_date("2007-01-25T12:00:00Z")
datetime.datetime(2007, 1, 25, 12, 0, tzinfo=<iso8601.Utc ...>)
>>>
"""
# __all__ = ["_parse_date", "_ParseError", "UTC", "_FixedOffset"]
# Adapted from http://delete.me.uk/2005/03/iso8601.html
ISO8601_REGEX = re.compile(
r"""
(?P<year>[0-9]{4})
(
(
(-(?P<monthdash>[0-9]{1,2}))
|
(?P<month>[0-9]{2})
(?!$) # Don't allow YYYYMM
)
(
(
(-(?P<daydash>[0-9]{1,2}))
|
(?P<day>[0-9]{2})
)
(
(
(?P<separator>[ T])
(?P<hour>[0-9]{2})
(:{0,1}(?P<minute>[0-9]{2})){0,1}
(
:{0,1}(?P<second>[0-9]{1,2})
([.,](?P<second_fraction>[0-9]+)){0,1}
){0,1}
(?P<timezone>
Z
|
(
(?P<tz_sign>[-+])
(?P<tz_hour>[0-9]{2})
:{0,1}
(?P<tz_minute>[0-9]{2}){0,1}
)
){0,1}
){0,1}
)
){0,1} # YYYY-MM
){0,1} # YYYY only
$
""",
re.VERBOSE,
)
class _ParseError(ValueError):
"""Raised when there is a problem parsing a date string"""
UTC = datetime.timezone.utc
def _FixedOffset(
offset_hours: float, offset_minutes: float, name: str
) -> datetime.timezone:
return datetime.timezone(
datetime.timedelta(hours=offset_hours, minutes=offset_minutes), name
)
def _parse_timezone(
matches: typing.Dict[str, str],
default_timezone: typing.Optional[datetime.timezone] = UTC,
) -> typing.Optional[datetime.timezone]:
"""Parses ISO 8601 time zone specs into tzinfo offsets"""
tz = matches.get("timezone", None)
if tz == "Z":
return UTC
# This isn't strictly correct, but it's common to encounter dates without
# timezones so I'll assume the default (which defaults to UTC).
# Addresses issue 4.
if tz is None:
return default_timezone
sign = matches.get("tz_sign", None)
hours = int(matches.get("tz_hour", 0))
minutes = int(matches.get("tz_minute", 0))
description = f"{sign}{hours:02d}:{minutes:02d}"
if sign == "-":
hours = -hours
minutes = -minutes
return _FixedOffset(hours, minutes, description)
def _parse_date(
datestring: str, default_timezone: typing.Optional[datetime.timezone] = UTC
) -> datetime.datetime:
"""Parses ISO 8601 dates into datetime objects
The timezone is parsed from the date string. However it is quite common to
have dates without a timezone (not strictly correct). In this case the
default timezone specified in default_timezone is used. This is UTC by
default.
:param datestring: The date to parse as a string
:param default_timezone: A datetime tzinfo instance to use when no timezone
is specified in the datestring. If this is set to
None then a naive datetime object is returned.
:returns: A datetime.datetime instance
:raises: _ParseError when there is a problem parsing the date or
constructing the datetime instance.
"""
try:
m = ISO8601_REGEX.match(datestring)
except Exception as e:
raise _ParseError(e)
if not m:
raise _ParseError(f"Unable to parse date string {datestring!r}")
# Drop any Nones from the regex matches
# TODO: check if there's a way to omit results in regexes
groups: typing.Dict[str, str] = {
k: v for k, v in m.groupdict().items() if v is not None
}
try:
return datetime.datetime(
year=int(groups.get("year", 0)),
month=int(groups.get("month", groups.get("monthdash", 1))),
day=int(groups.get("day", groups.get("daydash", 1))),
hour=int(groups.get("hour", 0)),
minute=int(groups.get("minute", 0)),
second=int(groups.get("second", 0)),
microsecond=int(
Decimal(f"0.{groups.get('second_fraction', 0)}") * Decimal("1000000.0")
),
tzinfo=_parse_timezone(groups, default_timezone=default_timezone),
)
except Exception as e:
raise _ParseError(e)
####################################################
def _process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (Dictionary) raw structured data to process
Returns:
Dictionary. Structured data to conform to the schema.
"""
# no further processing
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output = {}
if jc.utils.has_data(data):
dt = _parse_date(data)
raw_output = {
'year': dt.year,
'month': dt.strftime('%b'),
'month_num': dt.month,
'day': dt.day,
'weekday': dt.strftime('%a'),
'weekday_num': dt.isoweekday(),
'hour': int(dt.strftime('%I')),
'hour_24': dt.hour,
'minute': dt.minute,
'second': dt.second,
'microsecond': dt.microsecond,
'period': dt.strftime('%p').upper(),
'utc_offset': dt.strftime('%z') or None,
'day_of_year': int(dt.strftime('%j')),
'week_of_year': int(dt.strftime('%W')),
'iso': dt.isoformat(),
'timestamp': int(dt.timestamp())
}
return raw_output if raw else _process(raw_output)

View File

@@ -105,6 +105,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['df']
tags = ['command']
__version__ = info.version

View File

@@ -101,7 +101,7 @@ Schema:
]
[0] naive timestamp if "when" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -328,6 +328,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'aix', 'freebsd', 'darwin', 'win32', 'cygwin']
magic_commands = ['dig']
tags = ['command']
__version__ = info.version

View File

@@ -126,6 +126,7 @@ class info():
author = 'Rasheed Elsaleh'
author_email = 'rasheed@rebelliondefense.com'
compatible = ['win32']
tags = ['command']
__version__ = info.version

View File

@@ -131,6 +131,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['dmidecode']
tags = ['command']
__version__ = info.version

View File

@@ -138,6 +138,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['dpkg -l']
tags = ['command']
__version__ = info.version

View File

@@ -1,5 +1,9 @@
"""jc - JSON Convert `du` command output parser
The `du -h` option is not supported with the default output. If you
would like to use `du -h` or other options that change the output, be sure
to use `jc --raw` (cli) or `raw=True` (module).
Usage (cli):
$ du | jc --du
@@ -94,6 +98,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['du']
tags = ['command']
__version__ = info.version

View File

@@ -47,6 +47,7 @@ class info():
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'string']
__version__ = info.version

View File

@@ -78,6 +78,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['env', 'printenv']
tags = ['command']
__version__ = info.version

View File

@@ -69,6 +69,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['file']
tags = ['command']
__version__ = info.version

185
jc/parsers/findmnt.py Normal file
View File

@@ -0,0 +1,185 @@
"""jc - JSON Convert `findmnt` command output parser
Supports `-a`, `-l`, or no `findmnt` options.
> Note: Newer versions of `findmnt` have a JSON output option.
Usage (cli):
$ findmnt | jc --findmnt
or
$ jc findmnt
Usage (module):
import jc
result = jc.parse('findmnt', findmnt_command_output)
Schema:
[
{
"target": string,
"source": string,
"fstype": string,
"options": [
string
],
"kv_options": {
"<key_name>": string
}
]
Examples:
$ findmnt | jc --findmnt -p
[
{
"target": "/",
"source": "/dev/mapper/centos-root",
"fstype": "xfs",
"options": [
"rw",
"relatime",
"seclabel",
"attr2",
"inode64",
"noquota"
]
},
{
"target": "/sys/fs/cgroup",
"source": "tmpfs",
"fstype": "tmpfs",
"options": [
"ro",
"nosuid",
"nodev",
"noexec",
"seclabel"
],
"kv_options": {
"mode": "755"
}
},
...
]
$ findmnt | jc --findmnt -p -r
[
{
"target": "/",
"source": "/dev/mapper/centos-root",
"fstype": "xfs",
"options": "rw,relatime,seclabel,attr2,inode64,noquota"
},
{
"target": "/sys/fs/cgroup",
"source": "tmpfs",
"fstype": "tmpfs",
"options": "ro,nosuid,nodev,noexec,seclabel,mode=755"
},
...
]
"""
import re
from typing import List, Dict
from jc.jc_types import JSONDictType
from jc.parsers.universal import simple_table_parse
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.1'
description = '`findmnt` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['findmnt']
tags = ['command']
__version__ = info.version
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
# split normal options and k/v options
for item in proc_data:
reg_options = []
kv_options = {}
if 'options' in item:
opt_list = item['options'].split(',')
for option in opt_list:
if '=' in option:
k, v = option.split('=', maxsplit=1)
kv_options[k] = v
else:
reg_options.append(option)
if reg_options:
item['options'] = reg_options
if kv_options:
item['kv_options'] = kv_options
return proc_data
def _replace(matchobj):
if matchobj:
matchlen = len(matchobj.group(1))
return ' ' * matchlen + '/'
return ''
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[JSONDictType]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List[Dict] = []
table: List[str] = []
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
# remove initial drawing characters
line = re.sub(r'^([│ ├─└─|`-]+)/', _replace, line, count=1)
table.append(line)
table[0] = table[0].lower()
raw_output = simple_table_parse(table)
return raw_output if raw else _process(raw_output)

View File

@@ -98,6 +98,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'freebsd']
magic_commands = ['finger']
tags = ['command']
__version__ = info.version

View File

@@ -34,6 +34,7 @@ Examples:
[]
"""
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
@@ -47,13 +48,16 @@ class info():
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
# tags options: generic, standard, file, string, binary, command
tags = ['command']
magic_commands = ['foo']
__version__ = info.version
def _process(proc_data: List[Dict]) -> List[Dict]:
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
Final processing to conform to the schema.
@@ -78,7 +82,7 @@ def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[Dict]:
) -> List[JSONDictType]:
"""
Main text parsing function
@@ -95,7 +99,7 @@ def parse(
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List = []
raw_output: List[Dict] = []
if jc.utils.has_data(data):

View File

@@ -40,11 +40,12 @@ Examples:
{example output}
...
"""
from typing import Dict, Iterable, Union
from typing import Dict, Iterable
import jc.utils
from jc.streaming import (
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
)
from jc.jc_types import JSONDictType, StreamingOutputType
from jc.exceptions import ParseError
@@ -57,13 +58,16 @@ class info():
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
# tags options: generic, standard, file, string, binary, command
tags = ['command']
streaming = True
__version__ = info.version
def _process(proc_data: Dict) -> Dict:
def _process(proc_data: JSONDictType) -> JSONDictType:
"""
Final processing to conform to the schema.
@@ -90,7 +94,7 @@ def parse(
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False
) -> Union[Iterable[Dict], tuple]:
) -> StreamingOutputType:
"""
Main text parsing generator function. Returns an iterable object.
@@ -116,6 +120,10 @@ def parse(
streaming_line_input_type_check(line)
output_line: Dict = {}
# skip blank lines
if not line.strip():
continue
# parse the content here
# check out helper functions in jc.utils
# and jc.parsers.universal

View File

@@ -79,6 +79,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['free']
tags = ['command']
__version__ = info.version

View File

@@ -90,6 +90,7 @@ class info():
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'freebsd']
tags = ['file']
__version__ = info.version

View File

@@ -35,13 +35,13 @@ Schema:
[
{
"commit": string,
"author": string,
"author_email": string,
"author": string/null,
"author_email": string/null,
"date": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"commit_by": string,
"commit_by_email": string,
"commit_by": string/null,
"commit_by_email": string/null,
"commit_by_date": string,
"message": string,
"stats" : {
@@ -56,7 +56,7 @@ Schema:
]
[0] naive timestamp if "date" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -153,12 +153,13 @@ changes_pattern = re.compile(r'\s(?P<files>\d+)\s+(files? changed),\s+(?P<insert
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.2'
version = '1.3'
description = '`git log` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['git log']
tags = ['command']
__version__ = info.version
@@ -202,6 +203,28 @@ def _is_commit_hash(hash_string: str) -> bool:
return False
def _parse_name_email(line):
values = line.rsplit(maxsplit=1)
name = None
email = None
if len(values) == 2:
name = values[0]
if values[1].startswith('<') and values[1].endswith('>'):
email = values[1][1:-1]
else:
if values[0].lstrip().startswith('<') and values[0].endswith('>'):
email = values[0].lstrip()[1:-1]
else:
name = values[0]
if not name:
name = None
if not email:
email = None # covers '<>' case turning into null, not ''
return name, email
def parse(
data: str,
@@ -271,9 +294,7 @@ def parse(
continue
if line.startswith('Author: '):
values = line_list[1].rsplit(maxsplit=1)
output_line['author'] = values[0]
output_line['author_email'] = values[1].strip('<').strip('>')
output_line['author'], output_line['author_email'] = _parse_name_email(line_list[1])
continue
if line.startswith('Date: '):
@@ -289,9 +310,7 @@ def parse(
continue
if line.startswith('Commit: '):
values = line_list[1].rsplit(maxsplit=1)
output_line['commit_by'] = values[0]
output_line['commit_by_email'] = values[1].strip('<').strip('>')
output_line['commit_by'], output_line['commit_by_email'] = _parse_name_email(line_list[1])
continue
if line.startswith(' '):

View File

@@ -36,13 +36,13 @@ Schema:
{
"commit": string,
"author": string,
"author_email": string,
"author": string/null,
"author_email": string/null,
"date": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"commit_by": string,
"commit_by_email": string,
"commit_by": string/null,
"commit_by_email": string/null,
"commit_by_date": string,
"message": string,
"stats" : {
@@ -63,7 +63,7 @@ Schema:
}
[0] naive timestamp if "date" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -75,6 +75,7 @@ Examples:
import re
from typing import List, Dict, Iterable, Union
import jc.utils
from jc.parsers.git_log import _parse_name_email
from jc.streaming import (
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
)
@@ -87,11 +88,12 @@ changes_pattern = re.compile(r'\s(?P<files>\d+)\s+(files? changed),\s+(?P<insert
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.2'
version = '1.3'
description = '`git log` command streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['command']
streaming = True
@@ -215,9 +217,7 @@ def parse(
continue
if line.startswith('Author: '):
values = line_list[1].rsplit(maxsplit=1)
output_line['author'] = values[0]
output_line['author_email'] = values[1].strip('<').strip('>')
output_line['author'], output_line['author_email'] = _parse_name_email(line_list[1])
continue
if line.startswith('Date: '):
@@ -233,9 +233,7 @@ def parse(
continue
if line.startswith('Commit: '):
values = line_list[1].rsplit(maxsplit=1)
output_line['commit_by'] = values[0]
output_line['commit_by_email'] = values[1].strip('<').strip('>')
output_line['commit_by'], output_line['commit_by_email'] = _parse_name_email(line_list[1])
continue
if line.startswith(' '):

Some files were not shown because too many files have changed in this diff Show More