mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2026-04-03 17:44:07 +02:00
Compare commits
186 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
776ee66bae | ||
|
|
9bf2cd0691 | ||
|
|
fec74cf305 | ||
|
|
d3d7fbca61 | ||
|
|
550862a415 | ||
|
|
1763b530da | ||
|
|
8307150cae | ||
|
|
d2223c45d1 | ||
|
|
472ee5e295 | ||
|
|
1d0aebd836 | ||
|
|
8240626043 | ||
|
|
2cd14235c8 | ||
|
|
f774513554 | ||
|
|
388da9f003 | ||
|
|
fa18243491 | ||
|
|
5df1c1702b | ||
|
|
b6557802f4 | ||
|
|
15e3a511b6 | ||
|
|
08fbde0e8f | ||
|
|
28ebb4e8dd | ||
|
|
04fda57cbe | ||
|
|
b24495136c | ||
|
|
7d3fa55571 | ||
|
|
a76b5db8db | ||
|
|
667dd01ac7 | ||
|
|
559bee962a | ||
|
|
9f977d06e0 | ||
|
|
f67a916940 | ||
|
|
8a1308948f | ||
|
|
4e130d11a3 | ||
|
|
51aa5b268f | ||
|
|
6869133f53 | ||
|
|
ad3d88e47f | ||
|
|
6d29f8ba74 | ||
|
|
c7cb89e91d | ||
|
|
27f5118abd | ||
|
|
ac5a6e516d | ||
|
|
5d5bfbc1d1 | ||
|
|
9f4ba80000 | ||
|
|
c21c334b73 | ||
|
|
14093d9d43 | ||
|
|
176ca2f75d | ||
|
|
cfb71c7dad | ||
|
|
722eab83b1 | ||
|
|
d30edb2dae | ||
|
|
cba461ce8a | ||
|
|
f876505e25 | ||
|
|
5b9fcd5852 | ||
|
|
8a122cd9e1 | ||
|
|
557e68225c | ||
|
|
dc0947b87e | ||
|
|
af2c06cd28 | ||
|
|
67a4c6f797 | ||
|
|
0d1c857410 | ||
|
|
c7684dc94d | ||
|
|
a247572f64 | ||
|
|
306111303a | ||
|
|
c12b48537a | ||
|
|
0bf69713ab | ||
|
|
c05f1475ed | ||
|
|
416c262f02 | ||
|
|
40a5976f11 | ||
|
|
dc582fbec8 | ||
|
|
7047f0a449 | ||
|
|
d7a884a567 | ||
|
|
28de57792c | ||
|
|
a230cdbd21 | ||
|
|
251a261679 | ||
|
|
3baef254fd | ||
|
|
9e69e928b2 | ||
|
|
6eb595d2ca | ||
|
|
acf07a5144 | ||
|
|
7f53c58057 | ||
|
|
a069dc4855 | ||
|
|
febf544202 | ||
|
|
f2dd7b8815 | ||
|
|
d758e37fe3 | ||
|
|
9bc02a5623 | ||
|
|
eb0ec265d0 | ||
|
|
1f236dc02a | ||
|
|
86c279cbb2 | ||
|
|
4a7f1bed3a | ||
|
|
a730ae18c8 | ||
|
|
930bf439c0 | ||
|
|
f5f3133b87 | ||
|
|
cbca96de84 | ||
|
|
4d8ae3f124 | ||
|
|
653127431d | ||
|
|
22acef3765 | ||
|
|
0d5bf11f0d | ||
|
|
a824ccaff3 | ||
|
|
97ac965ba5 | ||
|
|
3e7f284df5 | ||
|
|
5c749fe26f | ||
|
|
aa48b46f48 | ||
|
|
6eaa4ae176 | ||
|
|
60c330b342 | ||
|
|
fdeb994121 | ||
|
|
65ed92fe7b | ||
|
|
9c8730786b | ||
|
|
7608823ea7 | ||
|
|
4f8c1a2ca2 | ||
|
|
37489dd4e1 | ||
|
|
a53aa1d0b8 | ||
|
|
f7b64a5762 | ||
|
|
9b1fe0d9a4 | ||
|
|
b876645fc5 | ||
|
|
d9c0b8f8ad | ||
|
|
78d2b239c8 | ||
|
|
5a12d98893 | ||
|
|
621f11e6f9 | ||
|
|
8417f2fe4e | ||
|
|
3ef2a0a065 | ||
|
|
faec16d1f2 | ||
|
|
a4ef52b533 | ||
|
|
0b407123c2 | ||
|
|
98eedc69ec | ||
|
|
dd231ae293 | ||
|
|
ad6196ddab | ||
|
|
49ca0cecf4 | ||
|
|
148f2fb6db | ||
|
|
e04cd298fb | ||
|
|
5bb4e2b4b6 | ||
|
|
7b22db50d3 | ||
|
|
fecb2193ae | ||
|
|
46af3bd0c0 | ||
|
|
c245c89f82 | ||
|
|
a8f0cd9dae | ||
|
|
3101189d47 | ||
|
|
3f0b644b85 | ||
|
|
25c2c483f8 | ||
|
|
8bc2ea14a3 | ||
|
|
8d4f22d9a5 | ||
|
|
d2adc2630c | ||
|
|
727f2b589e | ||
|
|
abbfc92da0 | ||
|
|
73b7e71cad | ||
|
|
4825b16f07 | ||
|
|
d2013366cc | ||
|
|
96609a2c70 | ||
|
|
39306573da | ||
|
|
01e330aa97 | ||
|
|
f08a74097d | ||
|
|
79e37a7383 | ||
|
|
3eebb6ee19 | ||
|
|
096fffdb79 | ||
|
|
728d882ed0 | ||
|
|
b53e42aca6 | ||
|
|
477329ce5b | ||
|
|
283dc4efd5 | ||
|
|
d490bbcaa0 | ||
|
|
f49ddf8e5c | ||
|
|
e1e341652b | ||
|
|
ecda667549 | ||
|
|
a0d96a188a | ||
|
|
6c0f0cddfe | ||
|
|
c7173ecd89 | ||
|
|
e98240c905 | ||
|
|
6cb7e25974 | ||
|
|
c37980c05c | ||
|
|
b5943bd39d | ||
|
|
49a3a7db3b | ||
|
|
0c55240e9d | ||
|
|
f91988aed5 | ||
|
|
3c3ad9fc6a | ||
|
|
291ab79e22 | ||
|
|
e6d5892c14 | ||
|
|
dcca7a57d5 | ||
|
|
4ee8a69337 | ||
|
|
c0414e7db7 | ||
|
|
a419175fe6 | ||
|
|
cd6dead034 | ||
|
|
45342ea9fe | ||
|
|
585bf0e159 | ||
|
|
3a860b9bab | ||
|
|
269180df77 | ||
|
|
a1afed8d95 | ||
|
|
e39f150a21 | ||
|
|
e85f11c6fc | ||
|
|
49a9d7b07e | ||
|
|
a2ef9c429e | ||
|
|
d5e9074f1c | ||
|
|
774699f085 | ||
|
|
7138eef3d1 | ||
|
|
fad5e544aa | ||
|
|
64757e2cf5 |
97
CHANGELOG
97
CHANGELOG
@@ -1,13 +1,50 @@
|
||||
jc changelog
|
||||
|
||||
20220531 v1.20.0
|
||||
- Add YAML output option with `-y`
|
||||
- Add `top -b` standard and streaming parsers tested on linux
|
||||
- Add `plugin_parser_count`, `standard_parser_count`, and `streaming_parser_count`
|
||||
keys to `jc -a` output
|
||||
- Add `is_compatible` function to the `utils` module
|
||||
- Fix `pip-show` parser for packages with a multi-line license field
|
||||
- Fix ASCII Table parser for cases where centered headers cause mis-aligned fields
|
||||
|
||||
20220513 v1.19.0
|
||||
- Add `chage --list` command parser tested on linux
|
||||
- Add `git log` command streaming parser
|
||||
- Fix `git log` standard parser for corner-cases where hash values are in messages
|
||||
- Fix `df` command parser for rare instances when a newline is found at the end
|
||||
- Allow jc to pip install on unsupported python version 3.6
|
||||
- Fix `asciitable-m` parser to skip some rows that contain column separator
|
||||
characters in cell data. A warning message will be printed to STDERR
|
||||
unless `-q` or `quiet=True` is used.
|
||||
|
||||
20220427 v1.18.8
|
||||
- Fix `update-alternatives --query` parser for cases where `slaves` are not present
|
||||
- Fix UnicodeEncodeError on some systems where LANG=C is set and unicode
|
||||
characters are in the output
|
||||
- Update `history` parser: do not drop non-ASCII characters if the system
|
||||
is configured for UTF-8 encoding
|
||||
- Enhance "magic syntax" to always use UTF-8 encoding
|
||||
|
||||
20220425 v1.18.7
|
||||
- Add `git log` command parser
|
||||
- Add `update-alternatives --query` parser
|
||||
- Add `update-alternatives --get-selections` parser
|
||||
- Fix key/value and ini parsers to allow duplicate keys
|
||||
- Fix yaml file parser for files including timestamp objects
|
||||
- Update `xrandr` parser: add a 'rotation' field
|
||||
- Fix failing tests by moving template files
|
||||
- Add python interpreter version and path to -v and -a output
|
||||
|
||||
20220325 v1.18.6
|
||||
- Add pidstat command parser tested on linux
|
||||
- Add pidstat command streaming parser tested on linux
|
||||
- Add mpstat command parser tested on linux
|
||||
- Add mpstat command streaming parser tested on linux
|
||||
- Add `pidstat` command parser tested on linux
|
||||
- Add `pidstat` command streaming parser tested on linux
|
||||
- Add `mpstat` command parser tested on linux
|
||||
- Add `mpstat` command streaming parser tested on linux
|
||||
- Add single-line ASCII and Unicode table parser
|
||||
- Add multi-line ASCII and Unicode table parser
|
||||
- Add documentation option to parser_info() and all_parser_info()
|
||||
- Add documentation option to `parser_info()` and `all_parser_info()`
|
||||
|
||||
20220305 v1.18.5
|
||||
- Fix date parser to ensure AM/PM period string is always uppercase
|
||||
@@ -361,16 +398,16 @@ jc changelog
|
||||
- Add axfr support for dig command parser
|
||||
|
||||
20200312 v1.9.2
|
||||
- Updated arp parser to fix OSX detection for some edge cases
|
||||
- Update arp parser to fix OSX detection for some edge cases
|
||||
|
||||
20200312 v1.9.1
|
||||
- Updated file command parser to make filename splitting more robust
|
||||
- Update file command parser to make filename splitting more robust
|
||||
|
||||
20200311 v1.9.0
|
||||
- Added ntpq command parser
|
||||
- Added timedatectl status command parser
|
||||
- Added airport -I and airport -s command parser
|
||||
- Added file command parser
|
||||
- Add ntpq command parser
|
||||
- Add timedatectl status command parser
|
||||
- Add airport -I and airport -s command parser
|
||||
- Add file command parser
|
||||
- Optimized history command parser by https://github.com/philippeitis
|
||||
- Magic syntax fix for certain edge cases
|
||||
|
||||
@@ -378,23 +415,23 @@ jc changelog
|
||||
- CLI optimizations by https://github.com/philippeitis
|
||||
- Refactored magic syntax function and added tests (https://github.com/philippeitis)
|
||||
- Github actions for CI testing on multiple platforms by https://github.com/philippeitis
|
||||
- Updated ls parser to fix parsing error in OSX with -lR when there are empty folders
|
||||
- Update ls parser to fix parsing error in OSX with -lR when there are empty folders
|
||||
|
||||
20200303 v1.8.0
|
||||
- Added blkid command parser
|
||||
- Added last and lastb command parser
|
||||
- Added who command parser
|
||||
- Added CSV file parser
|
||||
- Added /etc/passwd file parser
|
||||
- Added /etc/shadow file parser
|
||||
- Added /etc/group file parser
|
||||
- Added /etc/gshadow file parser
|
||||
- Add blkid command parser
|
||||
- Add last and lastb command parser
|
||||
- Add who command parser
|
||||
- Add CSV file parser
|
||||
- Add /etc/passwd file parser
|
||||
- Add /etc/shadow file parser
|
||||
- Add /etc/group file parser
|
||||
- Add /etc/gshadow file parser
|
||||
|
||||
20200227 v1.7.5
|
||||
- Updated ls parser to support filenames with newline characters
|
||||
- Update ls parser to support filenames with newline characters
|
||||
|
||||
20200219 v1.7.4
|
||||
- Updated ls parser to support multiple directories, globbing, and -R (recursive)
|
||||
- Update ls parser to support multiple directories, globbing, and -R (recursive)
|
||||
|
||||
20200211 v1.7.3
|
||||
- Add alternative 'magic' syntax: e.g. `jc ls -al`
|
||||
@@ -411,8 +448,8 @@ jc changelog
|
||||
- Add crontab file parser with user support (tested on linux)
|
||||
- Add __version__ variable to parser modules
|
||||
- Add exit code on error
|
||||
- Updated history parser to output "line" as an integer
|
||||
- Updated compatibility list for some parsers
|
||||
- Update history parser to output "line" as an integer
|
||||
- Update compatibility list for some parsers
|
||||
- Bugfix in crontab file parser: header insertion was clobbering first row
|
||||
- Just-in-time loading of parser modules instead of loading all at start
|
||||
|
||||
@@ -425,7 +462,7 @@ jc changelog
|
||||
- Add tests for ls, dig, ps, w, uptime on OSX
|
||||
- Add about option
|
||||
- Add universal parsers to refactor repetitive code
|
||||
- Updated ifconfig parser to output 'state' as an array
|
||||
- Update ifconfig parser to output 'state' as an array
|
||||
|
||||
20191117 v1.5.1
|
||||
- Add ss parser
|
||||
@@ -438,11 +475,11 @@ jc changelog
|
||||
- Add -d option to debug parsing issues
|
||||
- Add compatibility warnings to stderr
|
||||
- Add documentation
|
||||
- Updated iptables parser to allow --line-numbers option
|
||||
- Updated lsblk parser to allow parsing of added columns
|
||||
- Updated mount parser: changed 'access' field name to 'options'
|
||||
- Updated netstat parser to allow parsing of unix sockets and raw network connections
|
||||
- Updated w parser to fix unaligned data where blanks are possible
|
||||
- Update iptables parser to allow --line-numbers option
|
||||
- Update lsblk parser to allow parsing of added columns
|
||||
- Update mount parser: changed 'access' field name to 'options'
|
||||
- Update netstat parser to allow parsing of unix sockets and raw network connections
|
||||
- Update w parser to fix unaligned data where blanks are possible
|
||||
- Clean up code and reorganize package
|
||||
|
||||
20191031 v1.1.1
|
||||
|
||||
125
EXAMPLES.md
125
EXAMPLES.md
@@ -265,6 +265,21 @@ blkid -o udev -ip /dev/sda2 | jc --blkid -p # or: jc -p blkid -o udev
|
||||
}
|
||||
]
|
||||
```
|
||||
### chage --list
|
||||
```bash
|
||||
chage --list joeuser | jc --chage -p # or: jc -p chage --list joeuser
|
||||
```
|
||||
```json
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": 0,
|
||||
"max_days_between_password_change": 99999,
|
||||
"warning_days_before_password_expires": 7
|
||||
}
|
||||
```
|
||||
### cksum
|
||||
```bash
|
||||
cksum * | jc --cksum -p # or: jc -p cksum *
|
||||
@@ -1059,6 +1074,53 @@ cat /etc/fstab | jc --fstab -p
|
||||
}
|
||||
]
|
||||
```
|
||||
### git log
|
||||
```bash
|
||||
git log --stat | jc --git-log -p or: jc -p git log --stat
|
||||
```
|
||||
```json
|
||||
[
|
||||
{
|
||||
"commit": "728d882ed007b3c8b785018874a0eb06e1143b66",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:50:19 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 2,
|
||||
"insertions": 90,
|
||||
"deletions": 12,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"jc/parsers/git_log.py"
|
||||
]
|
||||
},
|
||||
"message": "add timestamp docs and examples",
|
||||
"epoch": 1650462619,
|
||||
"epoch_utc": null
|
||||
},
|
||||
{
|
||||
"commit": "b53e42aca623181aa9bc72194e6eeef1e9a3a237",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:44:42 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 5,
|
||||
"insertions": 29,
|
||||
"deletions": 6,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"docs/utils.md",
|
||||
"jc/parsers/git_log.py",
|
||||
"jc/utils.py",
|
||||
"man/jc.1"
|
||||
]
|
||||
},
|
||||
"message": "add calculated timestamp",
|
||||
"epoch": 1650462282,
|
||||
"epoch_utc": null
|
||||
}
|
||||
]
|
||||
```
|
||||
### /etc/group file
|
||||
```bash
|
||||
cat /etc/group | jc --group -p
|
||||
@@ -3645,6 +3707,69 @@ uname -a | jc --uname -p # or: jc -p uname -a
|
||||
"kernel_version": "#74-Ubuntu SMP Tue Sep 17 17:06:04 UTC 2019"
|
||||
}
|
||||
```
|
||||
### update-alternatives --get-selections
|
||||
```bash
|
||||
update-alternatives --get-selections | jc --update-alt-gs -p # or: jc -p update-alternatives --get-selections
|
||||
```
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": "arptables",
|
||||
"status": "auto",
|
||||
"current": "/usr/sbin/arptables-nft"
|
||||
},
|
||||
{
|
||||
"name": "awk",
|
||||
"status": "auto",
|
||||
"current": "/usr/bin/gawk"
|
||||
}
|
||||
]
|
||||
```
|
||||
### update-alternatives --query
|
||||
```bash
|
||||
update-alternatives --query editor | jc --update-alt-q -p # or: jc -p update-alternatives --query editor
|
||||
```
|
||||
```json
|
||||
{
|
||||
"name": "editor",
|
||||
"link": "/usr/bin/editor",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/editor.1.gz"
|
||||
},
|
||||
{
|
||||
"name": "editor.da.1.gz",
|
||||
"path": "/usr/share/man/da/man1/editor.1.gz"
|
||||
}
|
||||
],
|
||||
"status": "auto",
|
||||
"best": "/bin/nano",
|
||||
"value": "/bin/nano",
|
||||
"alternatives": [
|
||||
{
|
||||
"name": "/bin/ed",
|
||||
"priority": -100,
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/ed.1.gz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "/bin/nano",
|
||||
"priority": 40,
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/nano.1.gz"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### upower
|
||||
```bash
|
||||
upower -i /org/freedesktop/UPower/devices/battery | jc --upower -p # or jc -p upower -i /org/freedesktop/UPower/devices/battery
|
||||
|
||||
276
README.md
276
README.md
@@ -106,17 +106,18 @@ pip3 install jc
|
||||
|
||||
### OS Package Repositories
|
||||
|
||||
| OS | Command |
|
||||
|-----------------------|-------------------------------------------------------------------------------|
|
||||
| Debian/Ubuntu linux | `apt-get install jc` |
|
||||
| Fedora linux | `dnf install jc` |
|
||||
| openSUSE linux | `zypper install 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` |
|
||||
| macOS | `brew install jc` |
|
||||
| FreeBSD | `portsnap fetch update && cd /usr/ports/textproc/py-jc && make install clean` |
|
||||
| Ansible filter plugin | `ansible-galaxy collection install community.general` |
|
||||
| OS | Command |
|
||||
|--------------------------------------|-------------------------------------------------------------------------------|
|
||||
| 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` |
|
||||
| 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` |
|
||||
| macOS | `brew install jc` |
|
||||
| FreeBSD | `portsnap fetch update && cd /usr/ports/textproc/py-jc && make install clean` |
|
||||
| Ansible filter plugin | `ansible-galaxy collection install community.general` |
|
||||
|
||||
> For more OS Packages, see https://repology.org/project/jc/versions.
|
||||
|
||||
@@ -143,105 +144,114 @@ option.
|
||||
|
||||
### Parsers
|
||||
|
||||
- `--acpi` enables the `acpi` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi))
|
||||
- `--airport` enables the `airport -I` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/airport))
|
||||
- `--airport-s` enables the `airport -s` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s))
|
||||
- `--arp` enables the `arp` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/arp))
|
||||
- `--asciitable` enables the ASCII and Unicode table parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable))
|
||||
- `--asciitable-m` enables the multi-line ASCII and Unicode table parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m))
|
||||
- `--blkid` enables the `blkid` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid))
|
||||
- `--cksum` enables the `cksum` and `sum` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum))
|
||||
- `--crontab` enables the `crontab` command and file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab))
|
||||
- `--crontab-u` enables the `crontab` file parser with user support ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u))
|
||||
- `--csv` enables the CSV file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/csv))
|
||||
- `--csv-s` enables the CSV file streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s))
|
||||
- `--date` enables the `date` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/date))
|
||||
- `--df` enables the `df` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/df))
|
||||
- `--dig` enables the `dig` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dig))
|
||||
- `--dir` enables the `dir` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dir))
|
||||
- `--dmidecode` enables the `dmidecode` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dmidecode))
|
||||
- `--dpkg-l` enables the `dpkg -l` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dpkg_l))
|
||||
- `--du` enables the `du` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/du))
|
||||
- `--env` enables the `env` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/env))
|
||||
- `--file` enables the `file` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/file))
|
||||
- `--finger` enables the `finger` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/finger))
|
||||
- `--free` enables the `free` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/free))
|
||||
- `--fstab` enables the `/etc/fstab` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/fstab))
|
||||
- `--group` enables the `/etc/group` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/group))
|
||||
- `--gshadow` enables the `/etc/gshadow` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/gshadow))
|
||||
- `--hash` enables the `hash` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hash))
|
||||
- `--hashsum` enables the hashsum command parser (`md5sum`, `shasum`, etc.) ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hashsum))
|
||||
- `--hciconfig` enables the `hciconfig` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hciconfig))
|
||||
- `--history` enables the `history` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/history))
|
||||
- `--hosts` enables the `/etc/hosts` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hosts))
|
||||
- `--id` enables the `id` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/id))
|
||||
- `--ifconfig` enables the `ifconfig` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig))
|
||||
- `--ini` enables the INI file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ini))
|
||||
- `--iostat` enables the `iostat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat))
|
||||
- `--iostat-s` enables the `iostat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s))
|
||||
- `--iptables` enables the `iptables` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables))
|
||||
- `--iw-scan` enables the `iw dev [device] scan` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan))
|
||||
- `--jar-manifest` enables the MANIFEST.MF file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest))
|
||||
- `--jobs` enables the `jobs` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs))
|
||||
- `--kv` enables the Key/Value file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/kv))
|
||||
- `--last` enables the `last` and `lastb` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/last))
|
||||
- `--ls` enables the `ls` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ls))
|
||||
- `--ls-s` enables the `ls` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s))
|
||||
- `--lsblk` enables the `lsblk` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk))
|
||||
- `--lsmod` enables the `lsmod` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod))
|
||||
- `--lsof` enables the `lsof` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof))
|
||||
- `--lsusb` enables the `lsusb` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb))
|
||||
- `--mount` enables the `mount` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/mount))
|
||||
- `--mpstat` enables the `mpstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat))
|
||||
- `--mpstat-s` enables the `mpstat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s))
|
||||
- `--netstat` enables the `netstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat))
|
||||
- `--nmcli` enables the `nmcli` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli))
|
||||
- `--ntpq` enables the `ntpq -p` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq))
|
||||
- `--passwd` enables the `/etc/passwd` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd))
|
||||
- `--pidstat` enables the `pidstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat))
|
||||
- `--pidstat-s` enables the `pidstat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat_s))
|
||||
- `--ping` enables the `ping` and `ping6` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ping))
|
||||
- `--ping-s` enables the `ping` and `ping6` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ping_s))
|
||||
- `--pip-list` enables the `pip list` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_list))
|
||||
- `--pip-show` enables the `pip show` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_show))
|
||||
- `--ps` enables the `ps` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ps))
|
||||
- `--route` enables the `route` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/route))
|
||||
- `--rpm-qi` enables the `rpm -qi` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi))
|
||||
- `--rsync` enables the `rsync` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync))
|
||||
- `--rsync-s` enables the `rsync` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s))
|
||||
- `--sfdisk` enables the `sfdisk` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/sfdisk))
|
||||
- `--shadow` enables the `/etc/shadow` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/shadow))
|
||||
- `--ss` enables the `ss` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ss))
|
||||
- `--stat` enables the `stat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/stat))
|
||||
- `--stat-s` enables the `stat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s))
|
||||
- `--sysctl` enables the `sysctl` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl))
|
||||
- `--systemctl` enables the `systemctl` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl))
|
||||
- `--systemctl-lj` enables the `systemctl list-jobs` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj))
|
||||
- `--systemctl-ls` enables the `systemctl list-sockets` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls))
|
||||
- `--systemctl-luf` enables the `systemctl list-unit-files` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_luf))
|
||||
- `--systeminfo` enables the `systeminfo` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo))
|
||||
- `--time` enables the `/usr/bin/time` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/time))
|
||||
- `--timedatectl` enables the `timedatectl status` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl))
|
||||
- `--tracepath` enables the `tracepath` and `tracepath6` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath))
|
||||
- `--traceroute` enables the `traceroute` and `traceroute6` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute))
|
||||
- `--ufw` enables the `ufw status` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw))
|
||||
- `--ufw-appinfo` enables the `ufw app info [application]` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw_appinfo))
|
||||
- `--uname` enables the `uname -a` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/uname))
|
||||
- `--upower` enables the `upower` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/upower))
|
||||
- `--uptime` enables the `uptime` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/uptime))
|
||||
- `--vmstat` enables the `vmstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat))
|
||||
- `--vmstat-s` enables the `vmstat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat_s))
|
||||
- `--w` enables the `w` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/w))
|
||||
- `--wc` enables the `wc` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/wc))
|
||||
- `--who` enables the `who` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/who))
|
||||
- `--xml` enables the XML file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/xml))
|
||||
- `--xrandr` enables the `xrandr` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/xrandr))
|
||||
- `--yaml` enables the YAML file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/yaml))
|
||||
- `--zipinfo` enables the `zipinfo` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/zipinfo))
|
||||
| Argument | Command or Filetype | Documentation |
|
||||
|-------------------|---------------------------------------------------------|-------------------------------------------------------------------------|
|
||||
| ` --acpi` | `acpi` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi) |
|
||||
| ` --airport` | `airport -I` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/airport) |
|
||||
| ` --airport-s` | `airport -s` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s) |
|
||||
| ` --arp` | `arp` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/arp) |
|
||||
| ` --asciitable` | ASCII and Unicode table parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable) |
|
||||
| ` --asciitable-m` | multi-line ASCII and Unicode table parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m) |
|
||||
| ` --blkid` | `blkid` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid) |
|
||||
| ` --chage` | `chage --list` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/chage) |
|
||||
| ` --cksum` | `cksum` and `sum` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum) |
|
||||
| ` --crontab` | `crontab` command and file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab) |
|
||||
| ` --crontab-u` | `crontab` file parser with user support | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u) |
|
||||
| ` --csv` | CSV file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/csv) |
|
||||
| ` --csv-s` | CSV file streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s) |
|
||||
| ` --date` | `date` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/date) |
|
||||
| ` --df` | `df` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/df) |
|
||||
| ` --dig` | `dig` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dig) |
|
||||
| ` --dir` | `dir` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dir) |
|
||||
| ` --dmidecode` | `dmidecode` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dmidecode) |
|
||||
| ` --dpkg-l` | `dpkg -l` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dpkg_l) |
|
||||
| ` --du` | `du` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/du) |
|
||||
| ` --env` | `env` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/env) |
|
||||
| ` --file` | `file` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/file) |
|
||||
| ` --finger` | `finger` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/finger) |
|
||||
| ` --free` | `free` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/free) |
|
||||
| ` --fstab` | `/etc/fstab` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/fstab) |
|
||||
| ` --git-log` | `git log` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log) |
|
||||
| ` --git-log-s` | `git log` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log_s) |
|
||||
| ` --group` | `/etc/group` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/group) |
|
||||
| ` --gshadow` | `/etc/gshadow` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/gshadow) |
|
||||
| ` --hash` | `hash` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hash) |
|
||||
| ` --hashsum` | hashsum command parser (`md5sum`, `shasum`, etc.) | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hashsum) |
|
||||
| ` --hciconfig` | `hciconfig` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hciconfig) |
|
||||
| ` --history` | `history` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/history) |
|
||||
| ` --hosts` | `/etc/hosts` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hosts) |
|
||||
| ` --id` | `id` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/id) |
|
||||
| ` --ifconfig` | `ifconfig` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig) |
|
||||
| ` --ini` | INI file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ini) |
|
||||
| ` --iostat` | `iostat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat) |
|
||||
| ` --iostat-s` | `iostat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s) |
|
||||
| ` --iptables` | `iptables` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables) |
|
||||
| ` --iw-scan` | `iw dev [device] scan` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan) |
|
||||
| ` --jar-manifest` | MANIFEST.MF file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) |
|
||||
| ` --jobs` | `jobs` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs) |
|
||||
| ` --kv` | Key/Value file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/kv) |
|
||||
| ` --last` | `last` and `lastb` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/last) |
|
||||
| ` --ls` | `ls` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ls) |
|
||||
| ` --ls-s` | `ls` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s) |
|
||||
| ` --lsblk` | `lsblk` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk) |
|
||||
| ` --lsmod` | `lsmod` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod) |
|
||||
| ` --lsof` | `lsof` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof) |
|
||||
| ` --lsusb` | `lsusb` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb) |
|
||||
| ` --mount` | `mount` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/mount) |
|
||||
| ` --mpstat` | `mpstat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat) |
|
||||
| ` --mpstat-s` | `mpstat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s) |
|
||||
| ` --netstat` | `netstat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat) |
|
||||
| ` --nmcli` | `nmcli` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli) |
|
||||
| ` --ntpq` | `ntpq -p` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq) |
|
||||
| ` --passwd` | `/etc/passwd` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd) |
|
||||
| ` --pidstat` | `pidstat -h` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat) |
|
||||
| ` --pidstat-s` | `pidstat -h` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat_s) |
|
||||
| ` --ping` | `ping` and `ping6` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ping) |
|
||||
| ` --ping-s` | `ping` and `ping6` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ping_s) |
|
||||
| ` --pip-list` | `pip list` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_list) |
|
||||
| ` --pip-show` | `pip show` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_show) |
|
||||
| ` --ps` | `ps` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ps) |
|
||||
| ` --route` | `route` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/route) |
|
||||
| ` --rpm-qi` | `rpm -qi` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi) |
|
||||
| ` --rsync` | `rsync` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync) |
|
||||
| ` --rsync-s` | `rsync` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s) |
|
||||
| ` --sfdisk` | `sfdisk` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/sfdisk) |
|
||||
| ` --shadow` | `/etc/shadow` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/shadow) |
|
||||
| ` --ss` | `ss` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ss) |
|
||||
| ` --stat` | `stat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/stat) |
|
||||
| ` --stat-s` | `stat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s) |
|
||||
| ` --sysctl` | `sysctl` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl) |
|
||||
| ` --systemctl` | `systemctl` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl) |
|
||||
| ` --systemctl-lj` | `systemctl list-jobs` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj) |
|
||||
| ` --systemctl-ls` | `systemctl list-sockets` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls) |
|
||||
| `--systemctl-luf` | `systemctl list-unit-files` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_luf) |
|
||||
| ` --systeminfo` | `systeminfo` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo) |
|
||||
| ` --time` | `/usr/bin/time` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/time) |
|
||||
| ` --timedatectl` | `timedatectl status` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl) |
|
||||
| ` --top` | `top -b` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/top) |
|
||||
| ` --top-s` | `top -b` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
|
||||
| ` --tracepath` | `tracepath` and `tracepath6` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
|
||||
| ` --traceroute` | `traceroute` and `traceroute6` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute) |
|
||||
| ` --ufw` | `ufw status` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw) |
|
||||
| ` --ufw-appinfo` | `ufw app info [application]` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw_appinfo) |
|
||||
| ` --uname` | `uname -a` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/uname) |
|
||||
| `--update-alt-gs` | `update-alternatives --get-selections` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_gs) |
|
||||
| ` --update-alt-q` | `update-alternatives --query` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_q) |
|
||||
| ` --upower` | `upower` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/upower) |
|
||||
| ` --uptime` | `uptime` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/uptime) |
|
||||
| ` --vmstat` | `vmstat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat) |
|
||||
| ` --vmstat-s` | `vmstat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat_s) |
|
||||
| ` --w` | `w` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/w) |
|
||||
| ` --wc` | `wc` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/wc) |
|
||||
| ` --who` | `who` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/who) |
|
||||
| ` --xml` | XML file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/xml) |
|
||||
| ` --xrandr` | `xrandr` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/xrandr) |
|
||||
| ` --yaml` | YAML file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/yaml) |
|
||||
| ` --zipinfo` | `zipinfo` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/zipinfo) |
|
||||
|
||||
### Options
|
||||
- `-a` about `jc`. Prints information about `jc` and the parsers (in JSON, of
|
||||
course!)
|
||||
- `-a` about `jc`. Prints information about `jc` and the parsers (in JSON or
|
||||
YAML, of course!)
|
||||
- `-C` force color output even when using pipes (overrides `-m` and the
|
||||
`NO_COLOR` env variable)
|
||||
- `-d` debug mode. Prints trace messages if parsing issues are encountered (use
|
||||
@@ -255,6 +265,7 @@ option.
|
||||
values and no additional semantic processing
|
||||
- `-u` unbuffer output
|
||||
- `-v` version information
|
||||
- `-y` YAML output
|
||||
|
||||
### Exit Codes
|
||||
Any fatal errors within `jc` will generate an exit code of `100`, otherwise the
|
||||
@@ -301,11 +312,11 @@ color output will override both the `NO_COLOR` environment variable and the `-m`
|
||||
option.
|
||||
|
||||
### Streaming Parsers
|
||||
Most parsers load all of the data from STDIN, parse it, then output the entire
|
||||
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
|
||||
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
|
||||
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
|
||||
can sometimes process the data more quickly. Streaming parsers have slightly
|
||||
different behavior than standard parsers as outlined below.
|
||||
@@ -370,14 +381,14 @@ $ ping 1.1.1.1 | jc --ping-s -u | jq
|
||||
|
||||
#### Using Streaming Parsers as Python Modules
|
||||
|
||||
Streaming parsers accept any iterable object and return an iterator object
|
||||
(generator) allowing lazy processing of the data. The input data should
|
||||
iterate on lines of string data. Examples of good input data are `sys.stdin` or
|
||||
Streaming parsers accept any iterable object and return an iterable object
|
||||
allowing lazy processing of the data. The input data should iterate on lines
|
||||
of string data. Examples of good input data are `sys.stdin` or
|
||||
`str.splitlines()`.
|
||||
|
||||
To use the generator object in your code, simply loop through it or use the
|
||||
[next()](https://docs.python.org/3/library/functions.html#next) builtin
|
||||
function:
|
||||
To use the returned iterable object in your code, simply loop through it or
|
||||
use the [next()](https://docs.python.org/3/library/functions.html#next)
|
||||
builtin function:
|
||||
```python
|
||||
import jc
|
||||
|
||||
@@ -399,9 +410,9 @@ Local parser plugins are standard python module files. Use the
|
||||
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py)
|
||||
parser as a template and simply place a `.py` file in the `jcparsers` subfolder.
|
||||
|
||||
Local plugin filenames must be valid python module names, therefore must consist
|
||||
entirely of alphanumerics and start with a letter. Local plugins may override
|
||||
default parsers.
|
||||
Local plugin filenames must be valid python module names and therefore must
|
||||
start with a letter and consist entirely of alphanumerics and underscores.
|
||||
Local plugins may override default parsers.
|
||||
|
||||
> Note: The application data directory follows the
|
||||
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
||||
@@ -421,6 +432,9 @@ or by exporting to the environment before running commands:
|
||||
$ export LANG=C
|
||||
```
|
||||
|
||||
On some older systems UTF-8 output will be downgraded to ASCII with `\\u`
|
||||
escape sequences if the `C` locale does not support UTF-8 encoding.
|
||||
|
||||
#### Timezones
|
||||
|
||||
Some parsers have calculated epoch timestamp fields added to the output. Unless
|
||||
@@ -431,15 +445,30 @@ If a UTC timezone can be detected in the text of the command output, the
|
||||
timestamp will be timezone aware and have a `_utc` suffix on the key name.
|
||||
(e.g. `epoch_utc`) No other timezones are supported for aware timestamps.
|
||||
|
||||
## Use In Other Shells
|
||||
`jc` can be used in most any shell. Some modern shells have JSON deserialization
|
||||
and filtering capabilities built-in which makes using `jc` even more convenient.
|
||||
|
||||
For example, the following is possible in [NGS](https://ngs-lang.org/)
|
||||
(Next Generation Shell):
|
||||
```bash
|
||||
myvar = ``jc dig www.google.com``[0].answer[0].data
|
||||
```
|
||||
This runs `jc`, parses the output JSON, and assigs the resulting data structure
|
||||
to a variable in a single line of code.
|
||||
|
||||
For more examples of how to use `jc` in other shells, see this
|
||||
[wiki page](https://github.com/kellyjonbrazil/jc/wiki/Using-jc-With-Different-Shells).
|
||||
|
||||
## Compatibility
|
||||
Some parsers like `dig`, `xml`, `csv`, etc. will work on any platform. Other
|
||||
parsers that convert platform-specific output will generate a warning message if
|
||||
they are run on an unsupported platform. To see all parser information,
|
||||
including compatibility, run `jc -ap`.
|
||||
|
||||
You may still use a parser on an unsupported platform - for example, you may want
|
||||
to parse a file with linux `lsof` output on an macOS or Windows laptop. In that
|
||||
case you can suppress the warning message with the `-q` cli option or the
|
||||
You may still use a parser on an unsupported platform - for example, you may
|
||||
want to parse a file with linux `lsof` output on an macOS or Windows laptop. In
|
||||
that case you can suppress the warning message with the `-q` cli option or the
|
||||
`quiet=True` function parameter in `parse()`:
|
||||
|
||||
macOS:
|
||||
@@ -468,7 +497,8 @@ Tested on:
|
||||
## Contributions
|
||||
Feel free to add/improve code or parsers! You can use the
|
||||
[`jc/parsers/foo.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo.py)
|
||||
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py) parsers as a template and submit your parser with a pull request.
|
||||
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py) parsers as a template and submit your parser with a pull
|
||||
request.
|
||||
|
||||
Please see the [Contributing Guidelines](https://github.com/kellyjonbrazil/jc/blob/master/CONTRIBUTING.md) for more information.
|
||||
|
||||
|
||||
36
docgen.sh
36
docgen.sh
@@ -76,20 +76,30 @@ EOF
|
||||
)
|
||||
|
||||
cd jc
|
||||
echo Building docs for: package
|
||||
pydoc-markdown -m jc "${readme_config}" > ../docs/readme.md
|
||||
(
|
||||
echo Building docs for: package
|
||||
pydoc-markdown -m jc "${readme_config}" > ../docs/readme.md; echo "+++ package docs complete"
|
||||
) &
|
||||
|
||||
echo Building docs for: lib
|
||||
pydoc-markdown -m jc.lib "${toc_config}" > ../docs/lib.md
|
||||
(
|
||||
echo Building docs for: lib
|
||||
pydoc-markdown -m jc.lib "${toc_config}" > ../docs/lib.md; echo "+++ lib docs complete"
|
||||
) &
|
||||
|
||||
echo Building docs for: utils
|
||||
pydoc-markdown -m jc.utils "${toc_config}" > ../docs/utils.md
|
||||
(
|
||||
echo Building docs for: utils
|
||||
pydoc-markdown -m jc.utils "${toc_config}" > ../docs/utils.md; echo "+++ utils docs complete"
|
||||
) &
|
||||
|
||||
echo Building docs for: streaming
|
||||
pydoc-markdown -m jc.streaming "${toc_config}" > ../docs/streaming.md
|
||||
(
|
||||
echo Building docs for: streaming
|
||||
pydoc-markdown -m jc.streaming "${toc_config}" > ../docs/streaming.md; echo "+++ streaming docs complete"
|
||||
) &
|
||||
|
||||
echo Building docs for: universal parser
|
||||
pydoc-markdown -m jc.parsers.universal "${toc_config}" > ../docs/parsers/universal.md
|
||||
(
|
||||
echo Building docs for: universal parser
|
||||
pydoc-markdown -m jc.parsers.universal "${toc_config}" > ../docs/parsers/universal.md; echo "+++ universal parser docs complete"
|
||||
) &
|
||||
|
||||
# a bit of inception here... jc is being used to help
|
||||
# automate the generation of its own documentation. :)
|
||||
@@ -103,7 +113,7 @@ do
|
||||
done < <(jc -a | jq -c '.parsers[] | select(.plugin != true)')
|
||||
|
||||
for parser in "${parsers[@]}"
|
||||
do
|
||||
do (
|
||||
parser_name=$(jq -r '.name' <<< "$parser")
|
||||
compatible=$(jq -r '.compatible | join(", ")' <<< "$parser")
|
||||
version=$(jq -r '.version' <<< "$parser")
|
||||
@@ -117,4 +127,8 @@ do
|
||||
echo "Compatibility: ${compatible}" >> ../docs/parsers/"${parser_name}".md
|
||||
echo >> ../docs/parsers/"${parser_name}".md
|
||||
echo "Version ${version} by ${author} (${author_email})" >> ../docs/parsers/"${parser_name}".md
|
||||
echo "+++ ${parser_name} docs complete"
|
||||
) &
|
||||
done
|
||||
wait
|
||||
echo "Document Generation Complete"
|
||||
|
||||
@@ -68,7 +68,7 @@ Parameters:
|
||||
variants of the module name.
|
||||
|
||||
data: (string or data to parse (string for normal
|
||||
iterator) parsers, iterator of strings for
|
||||
iterable) parsers, iterable of strings for
|
||||
streaming parsers)
|
||||
|
||||
raw: (boolean) output preprocessed JSON if True
|
||||
|
||||
@@ -8,7 +8,12 @@ jc - JSON Convert `asciitable` parser
|
||||
This parser converts ASCII and Unicode text tables with single-line rows.
|
||||
|
||||
Column headers must be at least two spaces apart from each other and must
|
||||
be unique.
|
||||
be unique. For best results, column headers should be left-justified. If
|
||||
column separators are present, then non-left-justified headers will be fixed
|
||||
automatically.
|
||||
|
||||
Row separators are optional and are ignored. Each non-row-separator line is
|
||||
considered a separate row in the table.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -20,7 +25,7 @@ For example:
|
||||
│ hi there │ abc def │ 3.14 │
|
||||
╘══════════╧═════════╧════════╛
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
+-----------------------------+
|
||||
| foo bar baz |
|
||||
@@ -29,30 +34,30 @@ For example:
|
||||
| hi there abc def 3.14 |
|
||||
+-----------------------------+
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
| foo | bar | baz |
|
||||
|----------|---------|--------|
|
||||
| good day | | 12345 |
|
||||
| hi there | abc def | 3.14 |
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
foo bar baz
|
||||
--------- -------- ------
|
||||
good day 12345
|
||||
hi there abc def 3.14
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
foo bar baz
|
||||
good day 12345
|
||||
hi there abc def 3.14
|
||||
|
||||
etc...
|
||||
etc...
|
||||
|
||||
Headers (keys) are converted to snake-case. All values are returned as
|
||||
strings, except empty strings, which are converted to None/null.
|
||||
Headers (keys) are converted to snake-case. All values are returned as
|
||||
strings, except empty strings, which are converted to None/null.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -136,4 +141,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)
|
||||
|
||||
@@ -23,12 +23,18 @@ For example:
|
||||
╘══════════╧═════════╧════════╛
|
||||
|
||||
Cells with multiple lines within rows will be joined with a newline
|
||||
character ('\n').
|
||||
character ('\\n').
|
||||
|
||||
Headers (keys) are converted to snake-case and newlines between multi-line
|
||||
headers are joined with an underscore. All values are returned as strings,
|
||||
except empty strings, which are converted to None/null.
|
||||
|
||||
> Note: table column separator characters (e.g. `|`) cannot be present
|
||||
> inside the cell data. If detected, a warning message will be printed to
|
||||
> `STDERR` and the line will be skipped. The warning message can be
|
||||
> suppressed by using the `-q` command option or by setting `quiet=True` in
|
||||
> `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat table.txt | jc --asciitable-m
|
||||
@@ -62,7 +68,7 @@ Examples:
|
||||
> +==========+=========+========+' | jc --asciitable-m -p
|
||||
[
|
||||
{
|
||||
"foo": "good day\nmate",
|
||||
"foo": "good day\\nmate",
|
||||
"bar": "12345",
|
||||
"baz_buz": null
|
||||
},
|
||||
@@ -86,7 +92,7 @@ Examples:
|
||||
> ╘══════════╧═════════╧════════╛' | jc --asciitable-m -p
|
||||
[
|
||||
{
|
||||
"foo": "good day\nmate",
|
||||
"foo": "good day\\nmate",
|
||||
"bar": "12345",
|
||||
"baz_buz": null
|
||||
},
|
||||
@@ -120,4 +126,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)
|
||||
|
||||
82
docs/parsers/chage.md
Normal file
82
docs/parsers/chage.md
Normal file
@@ -0,0 +1,82 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.chage"></a>
|
||||
|
||||
# jc.parsers.chage
|
||||
|
||||
jc - JSON Convert `chage --list` command output parser
|
||||
|
||||
Supports `chage -l <username>` or `chage --list <username>`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ chage -l johndoe | jc --chage
|
||||
|
||||
or
|
||||
|
||||
$ jc chage -l johndoe
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('chage', chage_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"password_last_changed": string,
|
||||
"password_expires": string,
|
||||
"password_inactive": string,
|
||||
"account_expires": string,
|
||||
"min_days_between_password_change": integer,
|
||||
"max_days_between_password_change": integer,
|
||||
"warning_days_before_password_expires": integer
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ chage --list joeuser | jc --chage -p
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": 0,
|
||||
"max_days_between_password_change": 99999,
|
||||
"warning_days_before_password_expires": 7
|
||||
}
|
||||
|
||||
$ chage --list joeuser | jc --chage -p -r
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": "0",
|
||||
"max_days_between_password_change": "99999",
|
||||
"warning_days_before_password_expires": "7"
|
||||
}
|
||||
|
||||
<a id="jc.parsers.chage.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict
|
||||
```
|
||||
|
||||
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)
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
jc - JSON Convert `csv` file streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `csv` streaming parser will attempt to automatically detect the
|
||||
delimiter character. If the delimiter cannot be detected it will default
|
||||
to comma. The first row of the file must be a header row.
|
||||
|
||||
Note: The first 100 rows are read into memory to enable delimiter detection,
|
||||
then the rest of the rows are loaded lazily.
|
||||
> Note: The first 100 rows are read into memory to enable delimiter
|
||||
> detection, then the rest of the rows are loaded lazily.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -68,7 +68,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -79,13 +79,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
@@ -120,4 +120,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
@@ -19,7 +19,7 @@ time of the system the parser is run on)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
C:> dir | jc --dir
|
||||
C:\> dir | jc --dir
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -42,7 +42,7 @@ Schema:
|
||||
|
||||
Examples:
|
||||
|
||||
C:> dir | jc --dir -p
|
||||
C:\> dir | jc --dir -p
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
@@ -83,7 +83,7 @@ Examples:
|
||||
...
|
||||
]
|
||||
|
||||
C:> dir | jc --dir -p -r
|
||||
C:\> dir | jc --dir -p -r
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
|
||||
175
docs/parsers/git_log.md
Normal file
175
docs/parsers/git_log.md
Normal file
@@ -0,0 +1,175 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.git_log"></a>
|
||||
|
||||
# jc.parsers.git\_log
|
||||
|
||||
jc - JSON Convert `git log` command output parser
|
||||
|
||||
Can be used with the following format options:
|
||||
- `oneline`
|
||||
- `short`
|
||||
- `medium`
|
||||
- `full`
|
||||
- `fuller`
|
||||
|
||||
Additional options supported:
|
||||
- `--stat`
|
||||
- `--shortstat`
|
||||
|
||||
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):
|
||||
|
||||
$ git log | jc --git-log
|
||||
|
||||
or
|
||||
|
||||
$ jc git log
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('git_log', git_log_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"commit": string,
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
"message": string,
|
||||
"stats" : {
|
||||
"files_changed": integer,
|
||||
"insertions": integer,
|
||||
"deletions": integer,
|
||||
"files": [
|
||||
string
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
[0] naive timestamp if "date" field is parsable, else null
|
||||
[1] timezone aware timestamp availabe for UTC, else null
|
||||
|
||||
Examples:
|
||||
|
||||
$ git log --stat | jc --git-log -p
|
||||
[
|
||||
{
|
||||
"commit": "728d882ed007b3c8b785018874a0eb06e1143b66",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:50:19 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 2,
|
||||
"insertions": 90,
|
||||
"deletions": 12,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"jc/parsers/git_log.py"
|
||||
]
|
||||
},
|
||||
"message": "add timestamp docs and examples",
|
||||
"epoch": 1650462619,
|
||||
"epoch_utc": null
|
||||
},
|
||||
{
|
||||
"commit": "b53e42aca623181aa9bc72194e6eeef1e9a3a237",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:44:42 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 5,
|
||||
"insertions": 29,
|
||||
"deletions": 6,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"docs/utils.md",
|
||||
"jc/parsers/git_log.py",
|
||||
"jc/utils.py",
|
||||
"man/jc.1"
|
||||
]
|
||||
},
|
||||
"message": "add calculated timestamp",
|
||||
"epoch": 1650462282,
|
||||
"epoch_utc": null
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ git log --stat | jc --git-log -p -r
|
||||
[
|
||||
{
|
||||
"commit": "728d882ed007b3c8b785018874a0eb06e1143b66",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:50:19 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": "2",
|
||||
"insertions": "90",
|
||||
"deletions": "12",
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"jc/parsers/git_log.py"
|
||||
]
|
||||
},
|
||||
"message": "add timestamp docs and examples"
|
||||
},
|
||||
{
|
||||
"commit": "b53e42aca623181aa9bc72194e6eeef1e9a3a237",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:44:42 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": "5",
|
||||
"insertions": "29",
|
||||
"deletions": "6",
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"docs/utils.md",
|
||||
"jc/parsers/git_log.py",
|
||||
"jc/utils.py",
|
||||
"man/jc.1"
|
||||
]
|
||||
},
|
||||
"message": "add calculated timestamp"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
<a id="jc.parsers.git_log.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
|
||||
```
|
||||
|
||||
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.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
111
docs/parsers/git_log_s.md
Normal file
111
docs/parsers/git_log_s.md
Normal file
@@ -0,0 +1,111 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.git_log_s"></a>
|
||||
|
||||
# jc.parsers.git\_log\_s
|
||||
|
||||
jc - JSON Convert `git log` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Can be used with the following format options:
|
||||
- `oneline`
|
||||
- `short`
|
||||
- `medium`
|
||||
- `full`
|
||||
- `fuller`
|
||||
|
||||
Additional options supported:
|
||||
- `--stat`
|
||||
- `--shortstat`
|
||||
|
||||
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):
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('git_log_s', git_log_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"commit": string,
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
"message": string,
|
||||
"stats" : {
|
||||
"files_changed": integer,
|
||||
"insertions": integer,
|
||||
"deletions": integer,
|
||||
"files": [
|
||||
string
|
||||
]
|
||||
}
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] naive timestamp if "date" field is parsable, else null
|
||||
[1] timezone aware timestamp availabe for UTC, else null
|
||||
|
||||
Examples:
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
{"commit":"a730ae18c8e81c5261db132df73cd74f272a0a26","author":"Kelly...}
|
||||
{"commit":"930bf439c06c48a952baec05a9896c8d92b7693e","author":"Kelly...}
|
||||
...
|
||||
|
||||
<a id="jc.parsers.git_log_s.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
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.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
@@ -87,4 +87,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `ifconfig` command output parser
|
||||
|
||||
Note: No `ifconfig` options are supported.
|
||||
> Note: No `ifconfig` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
jc - JSON Convert `INI` file parser
|
||||
|
||||
Parses standard `INI` files and files containing simple key/value pairs.
|
||||
Delimiter can be `=` or `:`. Missing values are supported. Comment prefix
|
||||
can be `#` or `;`. Comments must be on their own line.
|
||||
|
||||
Note: Values starting and ending with 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()`.
|
||||
- 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.
|
||||
|
||||
> Note: Values starting and ending with 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):
|
||||
|
||||
@@ -24,8 +26,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
ini or key/value document converted to a dictionary - see the
|
||||
configparser standard library documentation for more details.
|
||||
ini or key/value document converted to a dictionary - see the configparser
|
||||
standard library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
@@ -89,4 +91,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `iostat` command output parser
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
|
||||
jc - JSON Convert `iostat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ iostat | jc --iostat-s
|
||||
|
||||
> Note: When piping `jc` converted `iostat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -112,7 +112,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -123,13 +123,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
|
||||
jc - JSON Convert `Key/Value` file parser
|
||||
|
||||
Supports files containing simple key/value pairs. Delimiter can be `=` or
|
||||
`:`. Missing values are supported. Comment prefix can be `#` or `;`.
|
||||
Comments must be on their own line.
|
||||
Supports files containing simple key/value pairs.
|
||||
|
||||
Note: Values starting and ending with 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()`.
|
||||
- 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.
|
||||
|
||||
> Note: Values starting and ending with 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):
|
||||
|
||||
@@ -24,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 configparser standard
|
||||
library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
@@ -78,4 +80,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
@@ -9,11 +9,12 @@ Options supported:
|
||||
- `lbaR1`
|
||||
- `--time-style=full-iso`
|
||||
|
||||
Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
parse filenames that include newline characters. Since `ls` does not encode
|
||||
newlines in filenames when outputting to a pipe it will cause `jc` to see
|
||||
multiple files instead of a single file if `-1`, `-l`, or `-b` is not used.
|
||||
Alternatively, `vdir` can be used, which is the same as running `ls -lb`.
|
||||
> Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
> parse filenames that include newline characters. Since `ls` does not
|
||||
> encode newlines in filenames when outputting to a pipe it will cause `jc`
|
||||
> to see multiple files instead of a single file if `-1`, `-l`, or `-b` is
|
||||
> not used. Alternatively, `vdir` can be used, which is the same as running
|
||||
> `ls -lb`.
|
||||
|
||||
The `epoch` calculated timestamp field is naive. (i.e. based on the local
|
||||
time of the system the parser is run on)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `ls` and `vdir` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires the `-l` option to be used on `ls`. If there are newline characters
|
||||
in the filename, then make sure to use the `-b` option on `ls`.
|
||||
@@ -81,7 +81,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -92,13 +92,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
@@ -22,9 +22,9 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Note: <item> object keynames are assigned directly from the lsusb
|
||||
output. If there are duplicate <item> names in a section, only the
|
||||
last one is converted.
|
||||
> Note: <item> object keynames are assigned directly from the lsusb
|
||||
> output. If there are duplicate <item> names in a section, only the
|
||||
> last one is converted.
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `mpstat` command output parser
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
jc - JSON Convert `mpstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -101,15 +101,13 @@ Examples:
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -120,13 +118,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -29,18 +29,18 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the -r or raw=True option to disable it.
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the `-r` or `raw=True` option to disable it.
|
||||
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
|
||||
[
|
||||
{
|
||||
"<key>": string/integer/float, [0]
|
||||
"<key>": string/integer/float, # [0]
|
||||
"dhcp4_option_x": {
|
||||
"name": string,
|
||||
"value": string/integer/float,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# jc.parsers.pidstat
|
||||
|
||||
jc - JSON Convert `pidstat` command output parser
|
||||
jc - JSON Convert `pidstat -h` command output parser
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
# jc.parsers.pidstat\_s
|
||||
|
||||
jc - JSON Convert `pidstat` command output streaming parser
|
||||
jc - JSON Convert `pidstat -h` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
@@ -16,11 +16,11 @@ Usage (cli):
|
||||
$ pidstat | jc --pidstat-s
|
||||
|
||||
> Note: When piping `jc` converted `pidstat` output to other processes it
|
||||
may appear the output is hanging due to the OS pipe buffers. This is
|
||||
because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> may appear the output is hanging due to the OS pipe buffers. This is
|
||||
> because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
> the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
> output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -83,15 +83,13 @@ Examples:
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -102,13 +100,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -9,8 +9,8 @@ Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
piped to `jc`.
|
||||
> Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
> piped to `jc`.
|
||||
|
||||
$ ping -c 3 1.2.3.4 | jc --ping
|
||||
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
|
||||
jc - JSON Convert `ping` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ ping | jc --ping-s
|
||||
$ ping 1.2.3.4 | jc --ping-s
|
||||
|
||||
> Note: When piping `jc` converted `ping` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output.
|
||||
See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output.
|
||||
> See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -88,7 +88,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -99,13 +99,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
@@ -70,7 +70,7 @@ Examples:
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data, raw=False, quiet=False)
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
|
||||
```
|
||||
|
||||
Main text parsing function
|
||||
@@ -88,4 +88,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)
|
||||
|
||||
@@ -22,20 +22,20 @@ Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"flags_pretty": [
|
||||
string
|
||||
string
|
||||
]
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Works with `rpm -qi [package]` or `rpm -qia`.
|
||||
The `..._epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on)
|
||||
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and is
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and are
|
||||
only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
jc - JSON Convert `rsync` command output parser
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -51,8 +51,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -61,7 +61,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
jc - JSON Convert `rsync` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -49,8 +49,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -59,7 +59,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
@@ -90,15 +90,13 @@ Examples:
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -109,13 +107,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `ss` command output parser
|
||||
|
||||
Extended information options like -e and -p are not supported and may cause
|
||||
parsing irregularities.
|
||||
Extended information options like `-e` and `-p` are not supported and may
|
||||
cause parsing irregularities.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -23,8 +23,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `stat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on).
|
||||
@@ -86,7 +86,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -97,13 +97,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
jc - JSON Convert `sysctl -a` command output parser
|
||||
|
||||
Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
key/value object will be output. An attempt is made to convert obvious
|
||||
integers and floats. If no conversion is desired, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
> key/value object will be output. An attempt is made to convert obvious
|
||||
> integers and floats. If no conversion is desired, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ used to redirect the output to a file that can be read by `jc`.
|
||||
Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT`
|
||||
so `jc` can receive it.
|
||||
|
||||
Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
`time` command.
|
||||
> Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
> `time` command.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -26,8 +26,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage,
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
|
||||
{
|
||||
"real_time": float,
|
||||
|
||||
339
docs/parsers/top.md
Normal file
339
docs/parsers/top.md
Normal file
@@ -0,0 +1,339 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.top"></a>
|
||||
|
||||
# jc.parsers.top
|
||||
|
||||
jc - JSON Convert `top -b` command output parser
|
||||
|
||||
Requires batch mode (`-b`). The `-n` option must also be used to limit
|
||||
the number of times `top` is run.
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b -n 3 | jc --top
|
||||
|
||||
or
|
||||
|
||||
$ jc top -b -n 3
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('top', top_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
All `-` values are converted to `null`
|
||||
|
||||
[
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b -n 3 | jc --top -p
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": 118,
|
||||
"users": 2,
|
||||
"load_1m": 0.0,
|
||||
"load_5m": 0.01,
|
||||
"load_15m": 0.05,
|
||||
"tasks_total": 108,
|
||||
"tasks_running": 2,
|
||||
"tasks_sleeping": 106,
|
||||
"tasks_stopped": 0,
|
||||
"tasks_zombie": 0,
|
||||
"cpu_user": 5.6,
|
||||
"cpu_sys": 11.1,
|
||||
"cpu_nice": 0.0,
|
||||
"cpu_idle": 83.3,
|
||||
"cpu_wait": 0.0,
|
||||
"cpu_hardware": 0.0,
|
||||
"cpu_software": 0.0,
|
||||
"cpu_steal": 0.0,
|
||||
"mem_total": 3.7,
|
||||
"mem_free": 3.3,
|
||||
"mem_used": 0.2,
|
||||
"mem_buff_cache": 0.2,
|
||||
"swap_total": 2.0,
|
||||
"swap_free": 2.0,
|
||||
"swap_used": 0.0,
|
||||
"mem_available": 3.3,
|
||||
"processes": [
|
||||
{
|
||||
"pid": 2225,
|
||||
"user": "kbrazil",
|
||||
"priority": 20,
|
||||
"nice": 0,
|
||||
"virtual_mem": 158.1,
|
||||
"resident_mem": 2.2,
|
||||
"shared_mem": 1.6,
|
||||
"status": "running",
|
||||
"percent_cpu": 12.5,
|
||||
"percent_mem": 0.1,
|
||||
"time_hundredths": "0:00.02",
|
||||
"command": "top",
|
||||
"parent_pid": 1884,
|
||||
"uid": 1000,
|
||||
"real_uid": 1000,
|
||||
"real_user": "kbrazil",
|
||||
"saved_uid": 1000,
|
||||
"saved_user": "kbrazil",
|
||||
"gid": 1000,
|
||||
"group": "kbrazil",
|
||||
"pgrp": 2225,
|
||||
"tty": "pts/0",
|
||||
"tty_process_gid": 2225,
|
||||
"session_id": 1884,
|
||||
"thread_count": 1,
|
||||
"last_used_processor": 0,
|
||||
"time": "0:00",
|
||||
"swap": 0.0,
|
||||
"code": 0.1,
|
||||
"data": 1.0,
|
||||
"major_page_fault_count": 0,
|
||||
"minor_page_fault_count": 736,
|
||||
"dirty_pages_count": 0,
|
||||
"sleeping_in_function": null,
|
||||
"flags": "..4.2...",
|
||||
"cgroups": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"supplementary_gids": [
|
||||
10,
|
||||
1000
|
||||
],
|
||||
"supplementary_groups": [
|
||||
"wheel",
|
||||
"kbrazil"
|
||||
],
|
||||
"thread_gid": 2225,
|
||||
"environment_variables": [
|
||||
"XDG_SESSION_ID=2",
|
||||
"HOSTNAME=localhost"
|
||||
],
|
||||
"major_page_fault_count_delta": 0,
|
||||
"minor_page_fault_count_delta": 4,
|
||||
"used": 2.2,
|
||||
"ipc_namespace_inode": 4026531839,
|
||||
"mount_namespace_inode": 4026531840,
|
||||
"net_namespace_inode": 4026531956,
|
||||
"pid_namespace_inode": 4026531836,
|
||||
"user_namespace_inode": 4026531837,
|
||||
"nts_namespace_inode": 4026531838
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
$ top -b -n 3 | jc --top -p -r
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": "1:18",
|
||||
"users": "2",
|
||||
"load_1m": "0.00",
|
||||
"load_5m": "0.01",
|
||||
"load_15m": "0.05",
|
||||
"tasks_total": "108",
|
||||
"tasks_running": "2",
|
||||
"tasks_sleeping": "106",
|
||||
"tasks_stopped": "0",
|
||||
"tasks_zombie": "0",
|
||||
"cpu_user": "5.6",
|
||||
"cpu_sys": "11.1",
|
||||
"cpu_nice": "0.0",
|
||||
"cpu_idle": "83.3",
|
||||
"cpu_wait": "0.0",
|
||||
"cpu_hardware": "0.0",
|
||||
"cpu_software": "0.0",
|
||||
"cpu_steal": "0.0",
|
||||
"swap_total": "2.0",
|
||||
"swap_free": "2.0",
|
||||
"swap_used": "0.0",
|
||||
"mem_available": "3.3",
|
||||
"processes": [
|
||||
{
|
||||
"PID": "2225",
|
||||
"USER": "kbrazil",
|
||||
"PR": "20",
|
||||
"NI": "0",
|
||||
"VIRT": "158.1m",
|
||||
"RES": "2.2m",
|
||||
"SHR": "1.6m",
|
||||
"S": "R",
|
||||
"%CPU": "12.5",
|
||||
"%MEM": "0.1",
|
||||
"TIME+": "0:00.02",
|
||||
"COMMAND": "top",
|
||||
"PPID": "1884",
|
||||
"UID": "1000",
|
||||
"RUID": "1000",
|
||||
"RUSER": "kbrazil",
|
||||
"SUID": "1000",
|
||||
"SUSER": "kbrazil",
|
||||
"GID": "1000",
|
||||
"GROUP": "kbrazil",
|
||||
"PGRP": "2225",
|
||||
"TTY": "pts/0",
|
||||
"TPGID": "2225",
|
||||
"SID": "1884",
|
||||
"nTH": "1",
|
||||
"P": "0",
|
||||
"TIME": "0:00",
|
||||
"SWAP": "0.0m",
|
||||
"CODE": "0.1m",
|
||||
"DATA": "1.0m",
|
||||
"nMaj": "0",
|
||||
"nMin": "736",
|
||||
"nDRT": "0",
|
||||
"WCHAN": "-",
|
||||
"Flags": "..4.2...",
|
||||
"CGROUPS": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"SUPGIDS": "10,1000",
|
||||
"SUPGRPS": "wheel,kbrazil",
|
||||
"TGID": "2225",
|
||||
"ENVIRON": "XDG_SESSION_ID=2 HOSTNAME=localhost S+",
|
||||
"vMj": "0",
|
||||
"vMn": "4",
|
||||
"USED": "2.2m",
|
||||
"nsIPC": "4026531839",
|
||||
"nsMNT": "4026531840",
|
||||
"nsNET": "4026531956",
|
||||
"nsPID": "4026531836",
|
||||
"nsUSER": "4026531837",
|
||||
"nsUTS": "4026531838"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
<a id="jc.parsers.top.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
|
||||
```
|
||||
|
||||
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)
|
||||
180
docs/parsers/top_s.md
Normal file
180
docs/parsers/top_s.md
Normal file
@@ -0,0 +1,180 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.top_s"></a>
|
||||
|
||||
# jc.parsers.top\_s
|
||||
|
||||
jc - JSON Convert `top -b` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires batch mode (`-b`).
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b | jc --top-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('top_s', top_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
],
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b | jc --top-s
|
||||
{"time":"11:24:50","uptime":2,"users":2,"load_1m":0.23,"load_5m":...}
|
||||
...
|
||||
|
||||
$ top -b | jc --top-s -r
|
||||
{"time":"11:24:50","uptime":"2 min","users":"2","load_1m":"0.23","lo...}
|
||||
...
|
||||
|
||||
<a id="jc.parsers.top_s.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
@@ -7,12 +7,12 @@ jc - JSON Convert `traceroute` command output parser
|
||||
|
||||
Supports `traceroute` and `traceroute6` output.
|
||||
|
||||
Note: On some operating systems you will need to redirect `STDERR` to
|
||||
`STDOUT` for destination info since the header line is sent to
|
||||
`STDERR`. A warning message will be printed to `STDERR` if the
|
||||
header row is not found.
|
||||
|
||||
e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
> Note: On some operating systems you will need to redirect `STDERR` to
|
||||
> `STDOUT` for destination info since the header line is sent to
|
||||
> `STDERR`. A warning message will be printed to `STDERR` if the
|
||||
> header row is not found.
|
||||
>
|
||||
> e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `uname -a` command output parser
|
||||
|
||||
Note: Must use `uname -a`
|
||||
> Note: Must use `uname -a`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
71
docs/parsers/update_alt_gs.md
Normal file
71
docs/parsers/update_alt_gs.md
Normal file
@@ -0,0 +1,71 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.update_alt_gs"></a>
|
||||
|
||||
# jc.parsers.update\_alt\_gs
|
||||
|
||||
jc - JSON Convert `update-alternatives --get-selections` command output parser
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ update-alternatives --get-selections | jc --update-alt-gs
|
||||
|
||||
or
|
||||
|
||||
$ jc update-alternatives --get-selections
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('update-alt-gs',
|
||||
update_alternatives_get_selections_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"name": string,
|
||||
"status": string,
|
||||
"current": string
|
||||
}
|
||||
]
|
||||
|
||||
Examples:
|
||||
|
||||
$ update-alternatives --get-selections | jc --update-alt-gs -p
|
||||
[
|
||||
{
|
||||
"name": "arptables",
|
||||
"status": "auto",
|
||||
"current": "/usr/sbin/arptables-nft"
|
||||
},
|
||||
{
|
||||
"name": "awk",
|
||||
"status": "auto",
|
||||
"current": "/usr/bin/gawk"
|
||||
}
|
||||
]
|
||||
|
||||
<a id="jc.parsers.update_alt_gs.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
|
||||
```
|
||||
|
||||
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)
|
||||
157
docs/parsers/update_alt_q.md
Normal file
157
docs/parsers/update_alt_q.md
Normal file
@@ -0,0 +1,157 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.update_alt_q"></a>
|
||||
|
||||
# jc.parsers.update\_alt\_q
|
||||
|
||||
jc - JSON Convert `update-alternatives --query` command output parser
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ update-alternatives --query | jc --update-alt-q
|
||||
|
||||
or
|
||||
|
||||
$ jc update-alternatives --query
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('update_alt_q',
|
||||
update_alternatives_query_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"name": string,
|
||||
"link": string,
|
||||
"slaves": [
|
||||
{
|
||||
"name": string,
|
||||
"path": string
|
||||
}
|
||||
],
|
||||
"status": string,
|
||||
"best": string,
|
||||
"value": string, # (null if 'none')
|
||||
"alternatives": [
|
||||
{
|
||||
"alternative": string,
|
||||
"priority": integer,
|
||||
"slaves": [
|
||||
{
|
||||
"name": string,
|
||||
"path": string
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ update-alternatives --query editor | jc --update-alt-q -p
|
||||
{
|
||||
"name": "editor",
|
||||
"link": "/usr/bin/editor",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/editor.1.gz"
|
||||
},
|
||||
{
|
||||
"name": "editor.da.1.gz",
|
||||
"path": "/usr/share/man/da/man1/editor.1.gz"
|
||||
}
|
||||
],
|
||||
"status": "auto",
|
||||
"best": "/bin/nano",
|
||||
"value": "/bin/nano",
|
||||
"alternatives": [
|
||||
{
|
||||
"alternative": "/bin/ed",
|
||||
"priority": -100,
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/ed.1.gz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alternative": "/bin/nano",
|
||||
"priority": 40,
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/nano.1.gz"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$ update-alternatives --query | jc --update-alt-q -p -r
|
||||
{
|
||||
"name": "editor",
|
||||
"link": "/usr/bin/editor",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/editor.1.gz"
|
||||
},
|
||||
{
|
||||
"name": "editor.da.1.gz",
|
||||
"path": "/usr/share/man/da/man1/editor.1.gz"
|
||||
}
|
||||
],
|
||||
"status": "auto",
|
||||
"best": "/bin/nano",
|
||||
"value": "/bin/nano",
|
||||
"alternatives": [
|
||||
{
|
||||
"alternative": "/bin/ed",
|
||||
"priority": "-100",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/ed.1.gz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alternative": "/bin/nano",
|
||||
"priority": "40",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/nano.1.gz"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
<a id="jc.parsers.update_alt_q.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict
|
||||
```
|
||||
|
||||
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)
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `vmstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Options supported: `-a`, `-w`, `-d`, `-t`
|
||||
|
||||
@@ -21,11 +21,11 @@ Usage (cli):
|
||||
$ vmstat | jc --vmstat-s
|
||||
|
||||
> Note: When piping `jc` converted `vmstat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -75,9 +75,9 @@ Schema:
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -116,13 +116,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -16,8 +16,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
XML Document converted to a Dictionary
|
||||
See https://github.com/martinblech/xmltodict for details
|
||||
XML Document converted to a Dictionary. See https://github.com/martinblech/xmltodict
|
||||
for details.
|
||||
|
||||
{
|
||||
"key1": string/object,
|
||||
|
||||
@@ -54,7 +54,8 @@ Schema:
|
||||
"offset_width": integer,
|
||||
"offset_height": integer,
|
||||
"dimension_width": integer,
|
||||
"dimension_height": integer
|
||||
"dimension_height": integer,
|
||||
"rotation": string
|
||||
}
|
||||
],
|
||||
"unassociated_devices": [
|
||||
@@ -130,7 +131,8 @@ Examples:
|
||||
"offset_width": 0,
|
||||
"offset_height": 0,
|
||||
"dimension_width": 310,
|
||||
"dimension_height": 170
|
||||
"dimension_height": 170,
|
||||
"rotation": "normal"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -160,4 +162,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.0 by Kevin Lyter (lyter_git at sent.com)
|
||||
Version 1.1 by Kevin Lyter (lyter_git at sent.com)
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
jc - JSON Convert `YAML` file parser
|
||||
|
||||
> Note: `datetime` objects will be converted to strings.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat foo.yaml | jc --yaml
|
||||
@@ -107,4 +109,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)
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
|
||||
jc - JSON Convert `zipinfo` command output parser
|
||||
|
||||
Options supported:
|
||||
- none
|
||||
|
||||
Note: The default listing format.
|
||||
> Note: No `zipinfo` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -26,11 +26,12 @@ https://github.com/kellyjonbrazil/jc/tree/master/docs
|
||||
|
||||
### Specific Version
|
||||
|
||||
Replace `<full_version_number>` - e.g. `1.17.7`:
|
||||
|
||||
`https://github.com/kellyjonbrazil/jc/tree/v<full_version_number>/docs`
|
||||
|
||||
Specific versions can also be selected by tag in the branch dropdown menu.
|
||||
> Replace `<full_version_number>` - e.g. `1.18.0`:
|
||||
|
||||
Specific versions can also be selected by tag in the branch Github dropdown
|
||||
menu.
|
||||
|
||||
## Usage Example
|
||||
|
||||
@@ -93,14 +94,14 @@ its module name.
|
||||
|
||||
### parser_mod_list
|
||||
|
||||
parser_mod_list() -> list
|
||||
parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of all available parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`.
|
||||
|
||||
### plugin_parser_mod_list
|
||||
|
||||
plugin_parser_mod_list() -> list
|
||||
plugin_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of plugin parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -108,7 +109,7 @@ Get a list of plugin parser module names to be used in
|
||||
|
||||
### standard_parser_mod_list
|
||||
|
||||
standard_parser_mod_list() -> list
|
||||
standard_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of standard parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -116,7 +117,7 @@ Get a list of standard parser module names to be used in
|
||||
|
||||
### streaming_parser_mod_list
|
||||
|
||||
streaming_parser_mod_list() -> list
|
||||
streaming_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of streaming parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* [jc.utils](#jc.utils)
|
||||
* [warning\_message](#jc.utils.warning_message)
|
||||
* [error\_message](#jc.utils.error_message)
|
||||
* [is\_compatible](#jc.utils.is_compatible)
|
||||
* [compatibility](#jc.utils.compatibility)
|
||||
* [has\_data](#jc.utils.has_data)
|
||||
* [convert\_to\_int](#jc.utils.convert_to_int)
|
||||
@@ -26,8 +27,8 @@ jc - JSON Convert utils
|
||||
def warning_message(message_lines: List[str]) -> None
|
||||
```
|
||||
|
||||
Prints warning message for non-fatal issues. The first line is
|
||||
prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Prints warning message to `STDERR` for non-fatal issues. The first line
|
||||
is prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
Parameters:
|
||||
@@ -46,7 +47,7 @@ Returns:
|
||||
def error_message(message_lines: List[str]) -> None
|
||||
```
|
||||
|
||||
Prints an error message for fatal issues. The first line is
|
||||
Prints an error message to `STDERR` for fatal issues. The first line is
|
||||
prepended with 'jc: Error - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
@@ -58,6 +59,16 @@ Returns:
|
||||
|
||||
None - just prints output to STDERR
|
||||
|
||||
<a id="jc.utils.is_compatible"></a>
|
||||
|
||||
### is\_compatible
|
||||
|
||||
```python
|
||||
def is_compatible(compatible: List) -> bool
|
||||
```
|
||||
|
||||
Returns True if the parser is compatible with the running OS platform.
|
||||
|
||||
<a id="jc.utils.compatibility"></a>
|
||||
|
||||
### compatibility
|
||||
@@ -68,8 +79,8 @@ def compatibility(mod_name: str,
|
||||
quiet: bool = False) -> None
|
||||
```
|
||||
|
||||
Checks for the parser's compatibility with the running OS
|
||||
platform.
|
||||
Checks for the parser's compatibility with the running OS platform and
|
||||
prints a warning message to `STDERR` if not compatible and quiet=False.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -187,7 +198,7 @@ class timestamp()
|
||||
|
||||
```python
|
||||
def __init__(datetime_string: str,
|
||||
format_hint: Union[List, Tuple, None] = None) -> None
|
||||
format_hint: Optional[Iterable] = None) -> None
|
||||
```
|
||||
|
||||
Input a datetime text string of several formats and convert to a
|
||||
@@ -198,7 +209,7 @@ Parameters:
|
||||
datetime_string (str): a string representation of a
|
||||
datetime in several supported formats
|
||||
|
||||
format_hint (list | tuple): an optional list of format ID
|
||||
format_hint (iterable): an optional iterable of format ID
|
||||
integers to instruct the timestamp object to try those
|
||||
formats first in the order given. Other formats will be
|
||||
tried after the format hint list is exhausted. This can
|
||||
|
||||
@@ -22,11 +22,12 @@ https://github.com/kellyjonbrazil/jc/tree/master/docs
|
||||
|
||||
### Specific Version
|
||||
|
||||
Replace `<full_version_number>` - e.g. `1.17.7`:
|
||||
|
||||
`https://github.com/kellyjonbrazil/jc/tree/v<full_version_number>/docs`
|
||||
|
||||
Specific versions can also be selected by tag in the branch dropdown menu.
|
||||
> Replace `<full_version_number>` - e.g. `1.18.0`:
|
||||
|
||||
Specific versions can also be selected by tag in the branch Github dropdown
|
||||
menu.
|
||||
|
||||
## Usage Example
|
||||
|
||||
@@ -89,14 +90,14 @@ its module name.
|
||||
|
||||
### parser_mod_list
|
||||
|
||||
parser_mod_list() -> list
|
||||
parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of all available parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`.
|
||||
|
||||
### plugin_parser_mod_list
|
||||
|
||||
plugin_parser_mod_list() -> list
|
||||
plugin_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of plugin parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -104,7 +105,7 @@ Get a list of plugin parser module names to be used in
|
||||
|
||||
### standard_parser_mod_list
|
||||
|
||||
standard_parser_mod_list() -> list
|
||||
standard_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of standard parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -112,7 +113,7 @@ Get a list of standard parser module names to be used in
|
||||
|
||||
### streaming_parser_mod_list
|
||||
|
||||
streaming_parser_mod_list() -> list
|
||||
streaming_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of streaming parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
|
||||
157
jc/cli.py
157
jc/cli.py
@@ -2,15 +2,16 @@
|
||||
JC cli module
|
||||
"""
|
||||
|
||||
import io
|
||||
import sys
|
||||
import os
|
||||
import textwrap
|
||||
import signal
|
||||
import shlex
|
||||
import subprocess
|
||||
import json
|
||||
from .lib import (__version__, parser_info, all_parser_info, parsers,
|
||||
_get_parser, _parser_is_streaming)
|
||||
_get_parser, _parser_is_streaming, standard_parser_mod_list,
|
||||
plugin_parser_mod_list, streaming_parser_mod_list)
|
||||
from . import utils
|
||||
from . import tracebackplus
|
||||
from .exceptions import LibraryNotInstalled, ParseError
|
||||
@@ -21,13 +22,12 @@ try:
|
||||
from pygments import highlight
|
||||
from pygments.style import Style
|
||||
from pygments.token import (Name, Number, String, Keyword)
|
||||
from pygments.lexers import JsonLexer
|
||||
from pygments.lexers.data import JsonLexer, YamlLexer
|
||||
from pygments.formatters import Terminal256Formatter
|
||||
PYGMENTS_INSTALLED = True
|
||||
except Exception:
|
||||
PYGMENTS_INSTALLED = False
|
||||
|
||||
|
||||
JC_ERROR_EXIT = 100
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ def set_env_colors(env_colors=None):
|
||||
|
||||
def piped_output(force_color):
|
||||
"""
|
||||
Return False if stdout is a TTY. True if output is being piped to
|
||||
Return False if `STDOUT` is a TTY. True if output is being piped to
|
||||
another program and foce_color is True. This allows forcing of ANSI
|
||||
color codes even when using pipes.
|
||||
"""
|
||||
@@ -177,7 +177,12 @@ def about_jc():
|
||||
'website': info.website,
|
||||
'copyright': info.copyright,
|
||||
'license': info.license,
|
||||
'python_version': '.'.join((str(sys.version_info.major), str(sys.version_info.minor), str(sys.version_info.micro))),
|
||||
'python_path': sys.executable,
|
||||
'parser_count': len(all_parser_info()),
|
||||
'standard_parser_count': len(standard_parser_mod_list()),
|
||||
'streaming_parser_count': len(streaming_parser_mod_list()),
|
||||
'plugin_parser_count': len(plugin_parser_mod_list()),
|
||||
'parsers': all_parser_info()
|
||||
}
|
||||
|
||||
@@ -208,6 +213,7 @@ def helptext():
|
||||
-r raw JSON output
|
||||
-u unbuffer output
|
||||
-v version info
|
||||
-y YAML output
|
||||
|
||||
Examples:
|
||||
Standard Syntax:
|
||||
@@ -249,18 +255,64 @@ def help_doc(options):
|
||||
|
||||
def versiontext():
|
||||
"""Return the version text"""
|
||||
py_ver = '.'.join((str(sys.version_info.major), str(sys.version_info.minor), str(sys.version_info.micro)))
|
||||
versiontext_string = f'''\
|
||||
jc version {info.version}
|
||||
jc version: {info.version}
|
||||
python interpreter version: {py_ver}
|
||||
python path: {sys.executable}
|
||||
|
||||
{info.website}
|
||||
{info.copyright}'''
|
||||
{info.copyright}
|
||||
'''
|
||||
return textwrap.dedent(versiontext_string)
|
||||
|
||||
|
||||
def json_out(data, pretty=False, env_colors=None, mono=False, piped_out=False):
|
||||
def yaml_out(data, pretty=False, env_colors=None, mono=False, piped_out=False, ascii_only=False):
|
||||
"""
|
||||
Return a YAML formatted string. String may include color codes. If the
|
||||
YAML library is not installed, output will fall back to JSON with a
|
||||
warning message to STDERR"""
|
||||
# make ruamel.yaml import optional
|
||||
try:
|
||||
from ruamel.yaml import YAML
|
||||
YAML_INSTALLED = True
|
||||
except Exception:
|
||||
YAML_INSTALLED = False
|
||||
|
||||
if YAML_INSTALLED:
|
||||
y_string_buf = io.BytesIO()
|
||||
# monkey patch to disable plugins since we don't use them and in
|
||||
# ruamel.yaml versions prior to 0.17.0 the use of __file__ in the
|
||||
# plugin code is incompatible with the pyoxidizer packager
|
||||
YAML.official_plug_ins = lambda a: []
|
||||
yaml=YAML()
|
||||
yaml.default_flow_style = False
|
||||
yaml.explicit_start = True
|
||||
yaml.allow_unicode = not ascii_only
|
||||
yaml.encoding = 'utf-8'
|
||||
yaml.dump(data, y_string_buf)
|
||||
y_string = y_string_buf.getvalue().decode('utf-8')[:-1]
|
||||
|
||||
if not mono and not piped_out:
|
||||
# set colors
|
||||
class JcStyle(Style):
|
||||
styles = set_env_colors(env_colors)
|
||||
|
||||
return str(highlight(y_string, YamlLexer(), Terminal256Formatter(style=JcStyle))[0:-1])
|
||||
|
||||
return y_string
|
||||
|
||||
utils.warning_message(['YAML Library not installed. Reverting to JSON output.'])
|
||||
return json_out(data, pretty=pretty, env_colors=env_colors, mono=mono, piped_out=piped_out, ascii_only=ascii_only)
|
||||
|
||||
|
||||
def json_out(data, pretty=False, env_colors=None, mono=False, piped_out=False, ascii_only=False):
|
||||
"""
|
||||
Return a JSON formatted string. String may include color codes or be
|
||||
pretty printed.
|
||||
"""
|
||||
import json
|
||||
|
||||
separators = (',', ':')
|
||||
indent = None
|
||||
|
||||
@@ -268,15 +320,54 @@ def json_out(data, pretty=False, env_colors=None, mono=False, piped_out=False):
|
||||
separators = None
|
||||
indent = 2
|
||||
|
||||
j_string = json.dumps(data, indent=indent, separators=separators, ensure_ascii=ascii_only)
|
||||
|
||||
if not mono and not piped_out:
|
||||
# set colors
|
||||
class JcStyle(Style):
|
||||
styles = set_env_colors(env_colors)
|
||||
|
||||
return str(highlight(json.dumps(data, indent=indent, separators=separators, ensure_ascii=False),
|
||||
JsonLexer(), Terminal256Formatter(style=JcStyle))[0:-1])
|
||||
return str(highlight(j_string, JsonLexer(), Terminal256Formatter(style=JcStyle))[0:-1])
|
||||
|
||||
return json.dumps(data, indent=indent, separators=separators, ensure_ascii=False)
|
||||
return j_string
|
||||
|
||||
|
||||
def safe_print_out(list_or_dict, pretty=None, env_colors=None, mono=None,
|
||||
piped_out=None, flush=None, yaml=None):
|
||||
"""Safely prints JSON or YAML output in both UTF-8 and ASCII systems"""
|
||||
if yaml:
|
||||
try:
|
||||
print(yaml_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out),
|
||||
flush=flush)
|
||||
except UnicodeEncodeError:
|
||||
print(yaml_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out,
|
||||
ascii_only=True),
|
||||
flush=flush)
|
||||
|
||||
else:
|
||||
try:
|
||||
print(json_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out),
|
||||
flush=flush)
|
||||
except UnicodeEncodeError:
|
||||
print(json_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out,
|
||||
ascii_only=True),
|
||||
flush=flush)
|
||||
|
||||
|
||||
def magic_parser(args):
|
||||
@@ -347,7 +438,8 @@ def run_user_command(command):
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
close_fds=False, # Allows inheriting file descriptors;
|
||||
universal_newlines=True) # useful for process substitution
|
||||
universal_newlines=True, # useful for process substitution
|
||||
encoding='UTF-8')
|
||||
stdout, stderr = proc.communicate()
|
||||
|
||||
return (
|
||||
@@ -406,6 +498,7 @@ def main():
|
||||
raw = 'r' in options
|
||||
unbuffer = 'u' in options
|
||||
version_info = 'v' in options
|
||||
yaml_out = 'y' in options
|
||||
|
||||
if verbose_debug:
|
||||
tracebackplus.enable(context=11)
|
||||
@@ -414,19 +507,20 @@ def main():
|
||||
mono = True
|
||||
|
||||
if about:
|
||||
print(json_out(about_jc(),
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color)))
|
||||
safe_print_out(about_jc(),
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color),
|
||||
yaml=yaml_out)
|
||||
sys.exit(0)
|
||||
|
||||
if help_me:
|
||||
print(help_doc(sys.argv))
|
||||
utils._safe_print(help_doc(sys.argv))
|
||||
sys.exit(0)
|
||||
|
||||
if version_info:
|
||||
print(versiontext())
|
||||
utils._safe_print(versiontext())
|
||||
sys.exit(0)
|
||||
|
||||
# if magic syntax used, try to run the command and error if it's not found, etc.
|
||||
@@ -441,7 +535,7 @@ def main():
|
||||
try:
|
||||
magic_stdout, magic_stderr, magic_exit_code = run_user_command(run_command)
|
||||
if magic_stderr:
|
||||
print(magic_stderr[:-1], file=sys.stderr)
|
||||
utils._safe_print(magic_stderr[:-1], file=sys.stderr)
|
||||
|
||||
except OSError as e:
|
||||
if debug:
|
||||
@@ -505,12 +599,13 @@ def main():
|
||||
quiet=quiet,
|
||||
ignore_exceptions=ignore_exceptions)
|
||||
for line in result:
|
||||
print(json_out(line,
|
||||
safe_print_out(line,
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color)),
|
||||
flush=unbuffer)
|
||||
piped_out=piped_output(force_color),
|
||||
flush=unbuffer,
|
||||
yaml=yaml_out)
|
||||
|
||||
sys.exit(combined_exit_code(magic_exit_code, 0))
|
||||
|
||||
@@ -520,12 +615,14 @@ def main():
|
||||
result = parser.parse(data,
|
||||
raw=raw,
|
||||
quiet=quiet)
|
||||
print(json_out(result,
|
||||
|
||||
safe_print_out(result,
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color)),
|
||||
flush=unbuffer)
|
||||
piped_out=piped_output(force_color),
|
||||
flush=unbuffer,
|
||||
yaml=yaml_out)
|
||||
|
||||
sys.exit(combined_exit_code(magic_exit_code, 0))
|
||||
|
||||
@@ -540,14 +637,6 @@ def main():
|
||||
])
|
||||
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
|
||||
|
||||
except json.JSONDecodeError:
|
||||
if debug:
|
||||
raise
|
||||
|
||||
utils.error_message(['There was an issue generating the JSON output.',
|
||||
'For details use the -d or -dd option.'])
|
||||
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
|
||||
|
||||
except Exception:
|
||||
if debug:
|
||||
raise
|
||||
|
||||
11
jc/lib.py
11
jc/lib.py
@@ -6,7 +6,7 @@ import importlib
|
||||
from typing import Dict, List, Iterable, Union, Iterator
|
||||
from jc import appdirs
|
||||
|
||||
__version__ = '1.18.6'
|
||||
__version__ = '1.20.0'
|
||||
|
||||
parsers = [
|
||||
'acpi',
|
||||
@@ -16,6 +16,7 @@ parsers = [
|
||||
'asciitable',
|
||||
'asciitable-m',
|
||||
'blkid',
|
||||
'chage',
|
||||
'cksum',
|
||||
'crontab',
|
||||
'crontab-u',
|
||||
@@ -33,6 +34,8 @@ parsers = [
|
||||
'finger',
|
||||
'free',
|
||||
'fstab',
|
||||
'git-log',
|
||||
'git-log-s',
|
||||
'group',
|
||||
'gshadow',
|
||||
'hash',
|
||||
@@ -88,11 +91,15 @@ parsers = [
|
||||
'systeminfo',
|
||||
'time',
|
||||
'timedatectl',
|
||||
'top',
|
||||
'top-s',
|
||||
'tracepath',
|
||||
'traceroute',
|
||||
'ufw',
|
||||
'ufw-appinfo',
|
||||
'uname',
|
||||
'update-alt-gs',
|
||||
'update-alt-q',
|
||||
'upower',
|
||||
'uptime',
|
||||
'vmstat',
|
||||
@@ -206,7 +213,7 @@ def parse(
|
||||
variants of the module name.
|
||||
|
||||
data: (string or data to parse (string for normal
|
||||
iterator) parsers, iterator of strings for
|
||||
iterable) parsers, iterable of strings for
|
||||
streaming parsers)
|
||||
|
||||
raw: (boolean) output preprocessed JSON if True
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
This parser converts ASCII and Unicode text tables with single-line rows.
|
||||
|
||||
Column headers must be at least two spaces apart from each other and must
|
||||
be unique.
|
||||
be unique. For best results, column headers should be left-justified. If
|
||||
column separators are present, then non-left-justified headers will be fixed
|
||||
automatically.
|
||||
|
||||
Row separators are optional and are ignored. Each non-row-separator line is
|
||||
considered a separate row in the table.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -15,7 +20,7 @@ For example:
|
||||
│ hi there │ abc def │ 3.14 │
|
||||
╘══════════╧═════════╧════════╛
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
+-----------------------------+
|
||||
| foo bar baz |
|
||||
@@ -24,30 +29,30 @@ For example:
|
||||
| hi there abc def 3.14 |
|
||||
+-----------------------------+
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
| foo | bar | baz |
|
||||
|----------|---------|--------|
|
||||
| good day | | 12345 |
|
||||
| hi there | abc def | 3.14 |
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
foo bar baz
|
||||
--------- -------- ------
|
||||
good day 12345
|
||||
hi there abc def 3.14
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
foo bar baz
|
||||
good day 12345
|
||||
hi there abc def 3.14
|
||||
|
||||
etc...
|
||||
etc...
|
||||
|
||||
Headers (keys) are converted to snake-case. All values are returned as
|
||||
strings, except empty strings, which are converted to None/null.
|
||||
Headers (keys) are converted to snake-case. All values are returned as
|
||||
strings, except empty strings, which are converted to None/null.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -117,7 +122,7 @@ from jc.parsers.universal import sparse_table_parse
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
version = '1.1'
|
||||
description = 'ASCII and Unicode table parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -222,18 +227,20 @@ def _is_separator(line: str) -> bool:
|
||||
|
||||
def _snake_case(line: str) -> str:
|
||||
"""
|
||||
replace spaces between words and special characters with an underscore
|
||||
and set to lowercase
|
||||
Replace spaces between words and special characters with an underscore
|
||||
and set to lowercase. Ignore the replacement char (�) used for header
|
||||
padding.
|
||||
"""
|
||||
line = re.sub(r'[^a-zA-Z0-9 ]', '_', line)
|
||||
return re.sub(r'\b \b', '_', line).lower()
|
||||
line = re.sub(r'[^a-zA-Z0-9� ]', '_', line) # special characters
|
||||
line = re.sub(r'\b \b', '_', line).lower() # spaces betwee words
|
||||
return line
|
||||
|
||||
|
||||
def _normalize_rows(table: str) -> List[str]:
|
||||
"""
|
||||
returns a List of row strings. Header is snake-cased
|
||||
"""
|
||||
result = []
|
||||
result: List[str] = []
|
||||
for line in table.splitlines():
|
||||
# skip blank lines
|
||||
if not line.strip():
|
||||
@@ -243,7 +250,36 @@ def _normalize_rows(table: str) -> List[str]:
|
||||
if _is_separator(line):
|
||||
continue
|
||||
|
||||
# data row - remove column separators
|
||||
# header or data row found - remove column separators
|
||||
if not result: # this is the header row
|
||||
# normalize the separator
|
||||
line = line.replace('│', '|')\
|
||||
.replace('┃', '|')\
|
||||
.replace('┆', '|')\
|
||||
.replace('┇', '|')\
|
||||
.replace('┊', '|')\
|
||||
.replace('┋', '|')\
|
||||
.replace('╎', '|')\
|
||||
.replace('╏', '|')\
|
||||
.replace('║', '|')
|
||||
|
||||
# find the number of chars to pad in front of headers that are too
|
||||
# far away from the separator. Replace spaces with unicode char: �
|
||||
# we will remove this char from headers after sparse_table_parse
|
||||
problem_header_pattern = re.compile(r'(?:\| )( +)([^|]+)')
|
||||
problem_headers = problem_header_pattern.findall(line)
|
||||
if problem_headers:
|
||||
for p_header in problem_headers:
|
||||
old_header = p_header[0] + p_header[1]
|
||||
sub_chars = '�' * len(p_header[0])
|
||||
new_header = sub_chars + p_header[1]
|
||||
line = line.replace(old_header, new_header)
|
||||
|
||||
line = line.replace('|', ' ')
|
||||
result.append(_snake_case(line))
|
||||
continue
|
||||
|
||||
# this is a data row
|
||||
line = line.replace('|', ' ')\
|
||||
.replace('│', ' ')\
|
||||
.replace('┃', ' ')\
|
||||
@@ -256,7 +292,6 @@ def _normalize_rows(table: str) -> List[str]:
|
||||
.replace('║', ' ')
|
||||
result.append(line)
|
||||
|
||||
result[0] = _snake_case(result[0])
|
||||
return result
|
||||
|
||||
|
||||
@@ -266,7 +301,8 @@ def _fixup_headers(table: List[Dict]) -> List[Dict]:
|
||||
for row in table:
|
||||
new_row = row.copy()
|
||||
for k in row:
|
||||
k_new = k
|
||||
# remove replacement character
|
||||
k_new = k.replace('�', '')
|
||||
# remove consecutive underscores
|
||||
k_new = re.sub(r'__+', '_', k_new)
|
||||
# remove trailing underscores
|
||||
|
||||
@@ -18,12 +18,18 @@ For example:
|
||||
╘══════════╧═════════╧════════╛
|
||||
|
||||
Cells with multiple lines within rows will be joined with a newline
|
||||
character ('\n').
|
||||
character ('\\n').
|
||||
|
||||
Headers (keys) are converted to snake-case and newlines between multi-line
|
||||
headers are joined with an underscore. All values are returned as strings,
|
||||
except empty strings, which are converted to None/null.
|
||||
|
||||
> Note: table column separator characters (e.g. `|`) cannot be present
|
||||
> inside the cell data. If detected, a warning message will be printed to
|
||||
> `STDERR` and the line will be skipped. The warning message can be
|
||||
> suppressed by using the `-q` command option or by setting `quiet=True` in
|
||||
> `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat table.txt | jc --asciitable-m
|
||||
@@ -57,7 +63,7 @@ Examples:
|
||||
> +==========+=========+========+' | jc --asciitable-m -p
|
||||
[
|
||||
{
|
||||
"foo": "good day\nmate",
|
||||
"foo": "good day\\nmate",
|
||||
"bar": "12345",
|
||||
"baz_buz": null
|
||||
},
|
||||
@@ -81,7 +87,7 @@ Examples:
|
||||
> ╘══════════╧═════════╧════════╛' | jc --asciitable-m -p
|
||||
[
|
||||
{
|
||||
"foo": "good day\nmate",
|
||||
"foo": "good day\\nmate",
|
||||
"bar": "12345",
|
||||
"baz_buz": null
|
||||
},
|
||||
@@ -101,7 +107,7 @@ from jc.exceptions import ParseError
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
version = '1.1'
|
||||
description = 'multi-line ASCII and Unicode table parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -377,20 +383,27 @@ def _collapse_headers(table: List[List[str]]) -> List[str]:
|
||||
return result
|
||||
|
||||
|
||||
def _collapse_data(table: List[List[List[str]]]) -> List[List[str]]:
|
||||
def _collapse_data(table: List[List[List[str]]], quiet=False) -> List[List[str]]:
|
||||
"""combine data rows to return a simple list of lists"""
|
||||
result: List[List[str]] = []
|
||||
|
||||
for row in table:
|
||||
new_row: List[str] = []
|
||||
for line in row:
|
||||
if new_row:
|
||||
for i, item in enumerate(line):
|
||||
new_row[i] = (new_row[i] + '\n' + item).strip()
|
||||
else:
|
||||
new_row = line
|
||||
for index, row in enumerate(table):
|
||||
try:
|
||||
new_row: List[str] = []
|
||||
for line in row:
|
||||
if new_row:
|
||||
for i, item in enumerate(line):
|
||||
new_row[i] = (new_row[i] + '\n' + item).strip()
|
||||
else:
|
||||
new_row = line
|
||||
|
||||
result.append(new_row)
|
||||
result.append(new_row)
|
||||
except IndexError:
|
||||
if not quiet:
|
||||
row_string = '\n'.join([' | '.join(l) for l in row])
|
||||
jc.utils.warning_message(
|
||||
[f'Possible table separator character found in row {index}: {row_string}. Skipping.']
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@@ -409,14 +422,14 @@ def _create_table_dict(header: List[str], data: List[List[str]]) -> List[Dict[st
|
||||
return table_list_dict
|
||||
|
||||
|
||||
def _parse_pretty(string: str) -> List[Dict[str, Optional[str]]]:
|
||||
def _parse_pretty(string: str, quiet: bool =False) -> List[Dict[str, Optional[str]]]:
|
||||
string_lines: List[str] = string.splitlines()
|
||||
clean: List[Tuple[int, List[str]]] = _normalize_rows(string_lines)
|
||||
raw_headers: List[List[str]] = _get_headers(clean)
|
||||
raw_data: List[List[List[str]]] = _get_data(clean)
|
||||
|
||||
new_headers: List[str] = _collapse_headers(raw_headers)
|
||||
new_data: List[List[str]] = _collapse_data(raw_data)
|
||||
new_data: List[List[str]] = _collapse_data(raw_data, quiet)
|
||||
final_table: List[Dict[str, Optional[str]]] = _create_table_dict(new_headers, new_data)
|
||||
|
||||
return final_table
|
||||
@@ -452,7 +465,7 @@ def parse(
|
||||
table_type = _table_sniff(data)
|
||||
|
||||
if table_type == 'pretty':
|
||||
raw_output = _parse_pretty(data)
|
||||
raw_output = _parse_pretty(data, quiet)
|
||||
elif table_type == 'markdown':
|
||||
raise ParseError('Only "pretty" tables supported with multiline. "markdown" table detected. Please try the "asciitable" parser.')
|
||||
else:
|
||||
|
||||
151
jc/parsers/chage.py
Normal file
151
jc/parsers/chage.py
Normal file
@@ -0,0 +1,151 @@
|
||||
"""jc - JSON Convert `chage --list` command output parser
|
||||
|
||||
Supports `chage -l <username>` or `chage --list <username>`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ chage -l johndoe | jc --chage
|
||||
|
||||
or
|
||||
|
||||
$ jc chage -l johndoe
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('chage', chage_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"password_last_changed": string,
|
||||
"password_expires": string,
|
||||
"password_inactive": string,
|
||||
"account_expires": string,
|
||||
"min_days_between_password_change": integer,
|
||||
"max_days_between_password_change": integer,
|
||||
"warning_days_before_password_expires": integer
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ chage --list joeuser | jc --chage -p
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": 0,
|
||||
"max_days_between_password_change": 99999,
|
||||
"warning_days_before_password_expires": 7
|
||||
}
|
||||
|
||||
$ chage --list joeuser | jc --chage -p -r
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": "0",
|
||||
"max_days_between_password_change": "99999",
|
||||
"warning_days_before_password_expires": "7"
|
||||
}
|
||||
"""
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`chage --list` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
magic_commands = ['chage --list', 'chage -l']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: Dict) -> Dict:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (Dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured to conform to the schema.
|
||||
"""
|
||||
int_list = ['min_days_between_password_change', 'max_days_between_password_change',
|
||||
'warning_days_before_password_expires']
|
||||
|
||||
for key in proc_data:
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> Dict:
|
||||
"""
|
||||
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: Dict = {}
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
for line in filter(None, data.splitlines()):
|
||||
key, val = line.split(':', maxsplit=1)
|
||||
key = key.strip()
|
||||
val = val.strip()
|
||||
|
||||
if key == 'Last password change':
|
||||
raw_output['password_last_changed'] = val
|
||||
continue
|
||||
|
||||
if key == 'Password expires':
|
||||
raw_output['password_expires'] = val
|
||||
continue
|
||||
|
||||
if key == 'Password inactive':
|
||||
raw_output['password_inactive'] = val
|
||||
continue
|
||||
|
||||
if key == 'Account expires':
|
||||
raw_output['account_expires'] = val
|
||||
continue
|
||||
|
||||
if key == 'Minimum number of days between password change':
|
||||
raw_output['min_days_between_password_change'] = val
|
||||
continue
|
||||
|
||||
if key == 'Maximum number of days between password change':
|
||||
raw_output['max_days_between_password_change'] = val
|
||||
continue
|
||||
|
||||
if key == 'Number of days of warning before password expires':
|
||||
raw_output['warning_days_before_password_expires'] = val
|
||||
continue
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
@@ -1,14 +1,14 @@
|
||||
"""jc - JSON Convert `csv` file streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `csv` streaming parser will attempt to automatically detect the
|
||||
delimiter character. If the delimiter cannot be detected it will default
|
||||
to comma. The first row of the file must be a header row.
|
||||
|
||||
Note: The first 100 rows are read into memory to enable delimiter detection,
|
||||
then the rest of the rows are loaded lazily.
|
||||
> Note: The first 100 rows are read into memory to enable delimiter
|
||||
> detection, then the rest of the rows are loaded lazily.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -95,7 +95,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -106,13 +106,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -99,7 +99,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.9'
|
||||
version = '1.10'
|
||||
description = '`df` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -208,7 +208,9 @@ def parse(data, raw=False, quiet=False):
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
jc.utils.input_type_check(data)
|
||||
|
||||
cleandata = data.splitlines()
|
||||
# remove blank lines
|
||||
cleandata = list(filter(None, data.splitlines()))
|
||||
|
||||
fix_data = []
|
||||
raw_output = []
|
||||
filesystem_map = {}
|
||||
|
||||
@@ -14,7 +14,7 @@ time of the system the parser is run on)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
C:> dir | jc --dir
|
||||
C:\> dir | jc --dir
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -37,7 +37,7 @@ Schema:
|
||||
|
||||
Examples:
|
||||
|
||||
C:> dir | jc --dir -p
|
||||
C:\> dir | jc --dir -p
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
@@ -78,7 +78,7 @@ Examples:
|
||||
...
|
||||
]
|
||||
|
||||
C:> dir | jc --dir -p -r
|
||||
C:\> dir | jc --dir -p -r
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `foo` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
<<Short foo description and caveats>>
|
||||
|
||||
@@ -40,7 +40,7 @@ Examples:
|
||||
{example output}
|
||||
...
|
||||
"""
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
@@ -90,9 +90,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -103,13 +103,10 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
329
jc/parsers/git_log.py
Normal file
329
jc/parsers/git_log.py
Normal file
@@ -0,0 +1,329 @@
|
||||
"""jc - JSON Convert `git log` command output parser
|
||||
|
||||
Can be used with the following format options:
|
||||
- `oneline`
|
||||
- `short`
|
||||
- `medium`
|
||||
- `full`
|
||||
- `fuller`
|
||||
|
||||
Additional options supported:
|
||||
- `--stat`
|
||||
- `--shortstat`
|
||||
|
||||
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):
|
||||
|
||||
$ git log | jc --git-log
|
||||
|
||||
or
|
||||
|
||||
$ jc git log
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('git_log', git_log_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"commit": string,
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
"message": string,
|
||||
"stats" : {
|
||||
"files_changed": integer,
|
||||
"insertions": integer,
|
||||
"deletions": integer,
|
||||
"files": [
|
||||
string
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
[0] naive timestamp if "date" field is parsable, else null
|
||||
[1] timezone aware timestamp availabe for UTC, else null
|
||||
|
||||
Examples:
|
||||
|
||||
$ git log --stat | jc --git-log -p
|
||||
[
|
||||
{
|
||||
"commit": "728d882ed007b3c8b785018874a0eb06e1143b66",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:50:19 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 2,
|
||||
"insertions": 90,
|
||||
"deletions": 12,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"jc/parsers/git_log.py"
|
||||
]
|
||||
},
|
||||
"message": "add timestamp docs and examples",
|
||||
"epoch": 1650462619,
|
||||
"epoch_utc": null
|
||||
},
|
||||
{
|
||||
"commit": "b53e42aca623181aa9bc72194e6eeef1e9a3a237",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:44:42 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 5,
|
||||
"insertions": 29,
|
||||
"deletions": 6,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"docs/utils.md",
|
||||
"jc/parsers/git_log.py",
|
||||
"jc/utils.py",
|
||||
"man/jc.1"
|
||||
]
|
||||
},
|
||||
"message": "add calculated timestamp",
|
||||
"epoch": 1650462282,
|
||||
"epoch_utc": null
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ git log --stat | jc --git-log -p -r
|
||||
[
|
||||
{
|
||||
"commit": "728d882ed007b3c8b785018874a0eb06e1143b66",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:50:19 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": "2",
|
||||
"insertions": "90",
|
||||
"deletions": "12",
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"jc/parsers/git_log.py"
|
||||
]
|
||||
},
|
||||
"message": "add timestamp docs and examples"
|
||||
},
|
||||
{
|
||||
"commit": "b53e42aca623181aa9bc72194e6eeef1e9a3a237",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:44:42 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": "5",
|
||||
"insertions": "29",
|
||||
"deletions": "6",
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"docs/utils.md",
|
||||
"jc/parsers/git_log.py",
|
||||
"jc/utils.py",
|
||||
"man/jc.1"
|
||||
]
|
||||
},
|
||||
"message": "add calculated timestamp"
|
||||
},
|
||||
...
|
||||
]
|
||||
"""
|
||||
import re
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
|
||||
hash_pattern = re.compile(r'(?:[0-9]|[a-f]){40}')
|
||||
changes_pattern = re.compile(r'\s(?P<files>\d+)\s+(files? changed),\s+(?P<insertions>\d+)\s(insertions?\(\+\))?(,\s+)?(?P<deletions>\d+)?(\s+deletions?\(\-\))?')
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
description = '`git log` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
magic_commands = ['git log']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: List[Dict]) -> List[Dict]:
|
||||
"""
|
||||
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 = ['files_changed', 'insertions', 'deletions']
|
||||
|
||||
for entry in proc_data:
|
||||
if 'date' in entry:
|
||||
ts = jc.utils.timestamp(entry['date'], format_hint=(1100,))
|
||||
entry['epoch'] = ts.naive
|
||||
entry['epoch_utc'] = ts.utc
|
||||
|
||||
if 'stats' in entry:
|
||||
for key in entry['stats']:
|
||||
if key in int_list:
|
||||
entry['stats'][key] = jc.utils.convert_to_int(entry['stats'][key])
|
||||
return proc_data
|
||||
|
||||
|
||||
def _is_commit_hash(hash_string: str) -> bool:
|
||||
# 0c55240e9da30ac4293dc324f1094de2abd3da91
|
||||
if len(hash_string) != 40:
|
||||
return False
|
||||
|
||||
if hash_pattern.match(hash_string):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
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 = []
|
||||
output_line: Dict = {}
|
||||
message_lines: List[str] = []
|
||||
file_list: List[str] = []
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
for line in data.splitlines():
|
||||
line_list = line.split(maxsplit=1)
|
||||
|
||||
# oneline style
|
||||
if not line.startswith(' ') and line_list and _is_commit_hash(line_list[0]):
|
||||
if output_line:
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
raw_output.append(output_line)
|
||||
output_line = {}
|
||||
message_lines = []
|
||||
file_list = []
|
||||
output_line = {
|
||||
'commit': line_list[0],
|
||||
'message': line_list[1]
|
||||
}
|
||||
continue
|
||||
|
||||
# all other styles
|
||||
if line.startswith('commit '):
|
||||
if output_line:
|
||||
if message_lines:
|
||||
output_line['message'] = '\n'.join(message_lines)
|
||||
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
raw_output.append(output_line)
|
||||
output_line = {}
|
||||
message_lines = []
|
||||
file_list = []
|
||||
output_line['commit'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Merge: '):
|
||||
output_line['merge'] = line_list[1]
|
||||
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('>')
|
||||
continue
|
||||
|
||||
if line.startswith('Date: '):
|
||||
output_line['date'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('AuthorDate: '):
|
||||
output_line['date'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('CommitDate: '):
|
||||
output_line['commit_by_date'] = line_list[1]
|
||||
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('>')
|
||||
continue
|
||||
|
||||
if line.startswith(' '):
|
||||
message_lines.append(line.strip())
|
||||
continue
|
||||
|
||||
if line.startswith(' ') and 'changed, ' not in line:
|
||||
# this is a file name
|
||||
file_name = line.split('|')[0].strip()
|
||||
file_list.append(file_name)
|
||||
continue
|
||||
|
||||
if line.startswith(' ') and 'changed, ' in line:
|
||||
# this is the stat summary
|
||||
changes = changes_pattern.match(line)
|
||||
if changes:
|
||||
files = changes['files']
|
||||
insertions = changes['insertions']
|
||||
deletions = changes['deletions']
|
||||
|
||||
output_line['stats'] = {
|
||||
'files_changed': files or '0',
|
||||
'insertions': insertions or '0',
|
||||
'deletions': deletions or '0'
|
||||
}
|
||||
|
||||
if output_line:
|
||||
if message_lines:
|
||||
output_line['message'] = '\n'.join(message_lines)
|
||||
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
282
jc/parsers/git_log_s.py
Normal file
282
jc/parsers/git_log_s.py
Normal file
@@ -0,0 +1,282 @@
|
||||
"""jc - JSON Convert `git log` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Can be used with the following format options:
|
||||
- `oneline`
|
||||
- `short`
|
||||
- `medium`
|
||||
- `full`
|
||||
- `fuller`
|
||||
|
||||
Additional options supported:
|
||||
- `--stat`
|
||||
- `--shortstat`
|
||||
|
||||
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):
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('git_log_s', git_log_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"commit": string,
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
"message": string,
|
||||
"stats" : {
|
||||
"files_changed": integer,
|
||||
"insertions": integer,
|
||||
"deletions": integer,
|
||||
"files": [
|
||||
string
|
||||
]
|
||||
}
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] naive timestamp if "date" field is parsable, else null
|
||||
[1] timezone aware timestamp availabe for UTC, else null
|
||||
|
||||
Examples:
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
{"commit":"a730ae18c8e81c5261db132df73cd74f272a0a26","author":"Kelly...}
|
||||
{"commit":"930bf439c06c48a952baec05a9896c8d92b7693e","author":"Kelly...}
|
||||
...
|
||||
"""
|
||||
import re
|
||||
from typing import List, Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
)
|
||||
from jc.exceptions import ParseError
|
||||
|
||||
|
||||
hash_pattern = re.compile(r'(?:[0-9]|[a-f]){40}')
|
||||
changes_pattern = re.compile(r'\s(?P<files>\d+)\s+(files? changed),\s+(?P<insertions>\d+)\s(insertions?\(\+\))?(,\s+)?(?P<deletions>\d+)?(\s+deletions?\(\-\))?')
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
description = '`git log` command streaming parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
streaming = True
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: Dict) -> Dict:
|
||||
"""
|
||||
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 = ['files_changed', 'insertions', 'deletions']
|
||||
|
||||
if 'date' in proc_data:
|
||||
ts = jc.utils.timestamp(proc_data['date'], format_hint=(1100,))
|
||||
proc_data['epoch'] = ts.naive
|
||||
proc_data['epoch_utc'] = ts.utc
|
||||
|
||||
if 'stats' in proc_data:
|
||||
for key in proc_data['stats']:
|
||||
if key in int_list:
|
||||
proc_data['stats'][key] = jc.utils.convert_to_int(proc_data['stats'][key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def _is_commit_hash(hash_string: str) -> bool:
|
||||
# 0c55240e9da30ac4293dc324f1094de2abd3da91
|
||||
if len(hash_string) != 40:
|
||||
return False
|
||||
|
||||
if hash_pattern.match(hash_string):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
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)
|
||||
|
||||
output_line: Dict = {}
|
||||
message_lines: List[str] = []
|
||||
file_list: List[str] = []
|
||||
|
||||
for line in data:
|
||||
try:
|
||||
streaming_line_input_type_check(line)
|
||||
|
||||
if line == '' or line == '\n':
|
||||
continue
|
||||
|
||||
line_list = line.rstrip().split(maxsplit=1)
|
||||
|
||||
# oneline style
|
||||
if not line.startswith(' ') and line_list and _is_commit_hash(line_list[0]):
|
||||
if output_line:
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
yield output_line if raw else _process(output_line)
|
||||
|
||||
output_line = {}
|
||||
message_lines = []
|
||||
file_list = []
|
||||
output_line = {
|
||||
'commit': line_list[0],
|
||||
'message': line_list[1]
|
||||
}
|
||||
continue
|
||||
|
||||
# all other styles
|
||||
if line.startswith('commit '):
|
||||
if output_line:
|
||||
if message_lines:
|
||||
output_line['message'] = '\n'.join(message_lines)
|
||||
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
yield output_line if raw else _process(output_line)
|
||||
|
||||
output_line = {}
|
||||
message_lines = []
|
||||
file_list = []
|
||||
output_line['commit'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Merge: '):
|
||||
output_line['merge'] = line_list[1]
|
||||
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('>')
|
||||
continue
|
||||
|
||||
if line.startswith('Date: '):
|
||||
output_line['date'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('AuthorDate: '):
|
||||
output_line['date'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('CommitDate: '):
|
||||
output_line['commit_by_date'] = line_list[1]
|
||||
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('>')
|
||||
continue
|
||||
|
||||
if line.startswith(' '):
|
||||
message_lines.append(line.strip())
|
||||
continue
|
||||
|
||||
if line.startswith(' ') and 'changed, ' not in line:
|
||||
# this is a file name
|
||||
file_name = line.split('|')[0].strip()
|
||||
file_list.append(file_name)
|
||||
continue
|
||||
|
||||
if line.startswith(' ') and 'changed, ' in line:
|
||||
# this is the stat summary
|
||||
changes = changes_pattern.match(line)
|
||||
if changes:
|
||||
files = changes['files']
|
||||
insertions = changes['insertions']
|
||||
deletions = changes['deletions']
|
||||
|
||||
output_line['stats'] = {
|
||||
'files_changed': files or '0',
|
||||
'insertions': insertions or '0',
|
||||
'deletions': deletions or '0'
|
||||
}
|
||||
continue
|
||||
|
||||
raise ParseError('Not git_log_s data')
|
||||
|
||||
except Exception as e:
|
||||
yield raise_or_yield(ignore_exceptions, e, line)
|
||||
|
||||
try:
|
||||
if output_line:
|
||||
if message_lines:
|
||||
output_line['message'] = '\n'.join(message_lines)
|
||||
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
yield output_line if raw else _process(output_line)
|
||||
|
||||
except Exception as e:
|
||||
yield raise_or_yield(ignore_exceptions, e, line)
|
||||
@@ -63,7 +63,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.6'
|
||||
version = '1.7'
|
||||
description = '`history` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -117,17 +117,14 @@ def parse(data, raw=False, quiet=False):
|
||||
raw_output = {}
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
linedata = data.splitlines()
|
||||
|
||||
# split lines and clear out any non-ascii chars
|
||||
linedata = data.encode('ascii', errors='ignore').decode().splitlines()
|
||||
|
||||
# Skip any blank lines
|
||||
for entry in filter(None, linedata):
|
||||
try:
|
||||
parsed_line = entry.split(maxsplit=1)
|
||||
raw_output[parsed_line[0]] = parsed_line[1]
|
||||
except IndexError:
|
||||
# need to catch indexerror in case there is weird input from prior commands
|
||||
number, command = entry.split(maxsplit=1)
|
||||
raw_output[number] = command
|
||||
except ValueError:
|
||||
# need to catch ValueError in case there is weird input from prior commands
|
||||
pass
|
||||
|
||||
if raw:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `ifconfig` command output parser
|
||||
|
||||
Note: No `ifconfig` options are supported.
|
||||
> Note: No `ifconfig` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"""jc - JSON Convert `INI` file parser
|
||||
|
||||
Parses standard `INI` files and files containing simple key/value pairs.
|
||||
Delimiter can be `=` or `:`. Missing values are supported. Comment prefix
|
||||
can be `#` or `;`. Comments must be on their own line.
|
||||
|
||||
Note: Values starting and ending with 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()`.
|
||||
- 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.
|
||||
|
||||
> Note: Values starting and ending with 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):
|
||||
|
||||
@@ -19,8 +21,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
ini or key/value document converted to a dictionary - see the
|
||||
configparser standard library documentation for more details.
|
||||
ini or key/value document converted to a dictionary - see the configparser
|
||||
standard library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
@@ -67,7 +69,7 @@ import configparser
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.5'
|
||||
version = '1.6'
|
||||
description = 'INI file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -135,7 +137,9 @@ def parse(data, raw=False, quiet=False):
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
ini = configparser.ConfigParser(allow_no_value=True, interpolation=None)
|
||||
ini = configparser.ConfigParser(allow_no_value=True,
|
||||
interpolation=None,
|
||||
strict=False)
|
||||
try:
|
||||
ini.read_string(data)
|
||||
raw_output = {s: dict(ini.items(s)) for s in ini.sections()}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `iostat` command output parser
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
"""jc - JSON Convert `iostat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ iostat | jc --iostat-s
|
||||
|
||||
> Note: When piping `jc` converted `iostat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -163,7 +163,7 @@ def _create_obj_list(section_list, section_name):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -174,13 +174,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"""jc - JSON Convert `Key/Value` file parser
|
||||
|
||||
Supports files containing simple key/value pairs. Delimiter can be `=` or
|
||||
`:`. Missing values are supported. Comment prefix can be `#` or `;`.
|
||||
Comments must be on their own line.
|
||||
Supports files containing simple key/value pairs.
|
||||
|
||||
Note: Values starting and ending with 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()`.
|
||||
- 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.
|
||||
|
||||
> Note: Values starting and ending with 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):
|
||||
|
||||
@@ -19,8 +21,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 configparser standard
|
||||
library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
@@ -52,7 +54,7 @@ Examples:
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = 'Key/Value file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
@@ -4,11 +4,12 @@ Options supported:
|
||||
- `lbaR1`
|
||||
- `--time-style=full-iso`
|
||||
|
||||
Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
parse filenames that include newline characters. Since `ls` does not encode
|
||||
newlines in filenames when outputting to a pipe it will cause `jc` to see
|
||||
multiple files instead of a single file if `-1`, `-l`, or `-b` is not used.
|
||||
Alternatively, `vdir` can be used, which is the same as running `ls -lb`.
|
||||
> Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
> parse filenames that include newline characters. Since `ls` does not
|
||||
> encode newlines in filenames when outputting to a pipe it will cause `jc`
|
||||
> to see multiple files instead of a single file if `-1`, `-l`, or `-b` is
|
||||
> not used. Alternatively, `vdir` can be used, which is the same as running
|
||||
> `ls -lb`.
|
||||
|
||||
The `epoch` calculated timestamp field is naive. (i.e. based on the local
|
||||
time of the system the parser is run on)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `ls` and `vdir` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires the `-l` option to be used on `ls`. If there are newline characters
|
||||
in the filename, then make sure to use the `-b` option on `ls`.
|
||||
@@ -118,7 +118,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -129,13 +129,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -17,9 +17,9 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Note: <item> object keynames are assigned directly from the lsusb
|
||||
output. If there are duplicate <item> names in a section, only the
|
||||
last one is converted.
|
||||
> Note: <item> object keynames are assigned directly from the lsusb
|
||||
> output. If there are duplicate <item> names in a section, only the
|
||||
> last one is converted.
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `mpstat` command output parser
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"""jc - JSON Convert `mpstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -90,7 +90,7 @@ Examples:
|
||||
{"cpu":"all","intr_s":"37.61","type":"interrupts","time":"03:15:06 PM"}
|
||||
...
|
||||
"""
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.parsers.universal import simple_table_parse
|
||||
from jc.streaming import (
|
||||
@@ -145,9 +145,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -158,13 +158,9 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -24,18 +24,18 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the -r or raw=True option to disable it.
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the `-r` or `raw=True` option to disable it.
|
||||
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
|
||||
[
|
||||
{
|
||||
"<key>": string/integer/float, [0]
|
||||
"<key>": string/integer/float, # [0]
|
||||
"dhcp4_option_x": {
|
||||
"name": string,
|
||||
"value": string/integer/float,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""jc - JSON Convert `pidstat` command output parser
|
||||
"""jc - JSON Convert `pidstat -h` command output parser
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
@@ -129,7 +129,7 @@ from jc.exceptions import ParseError
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`pidstat` command parser'
|
||||
description = '`pidstat -h` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `pidstat` command output streaming parser
|
||||
"""jc - JSON Convert `pidstat -h` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
@@ -11,11 +11,11 @@ Usage (cli):
|
||||
$ pidstat | jc --pidstat-s
|
||||
|
||||
> Note: When piping `jc` converted `pidstat` output to other processes it
|
||||
may appear the output is hanging due to the OS pipe buffers. This is
|
||||
because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> may appear the output is hanging due to the OS pipe buffers. This is
|
||||
> because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
> the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
> output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -72,7 +72,7 @@ Examples:
|
||||
{"time":"1646859134","uid":"0","pid":"9","percent_usr":"0.00","perc...}
|
||||
...
|
||||
"""
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
@@ -84,7 +84,7 @@ from jc.exceptions import ParseError
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`pidstat` command streaming parser'
|
||||
description = '`pidstat -h` command streaming parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
@@ -126,9 +126,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -139,13 +139,9 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -4,8 +4,8 @@ Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
piped to `jc`.
|
||||
> Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
> piped to `jc`.
|
||||
|
||||
$ ping -c 3 1.2.3.4 | jc --ping
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
"""jc - JSON Convert `ping` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ ping | jc --ping-s
|
||||
$ ping 1.2.3.4 | jc --ping-s
|
||||
|
||||
> Note: When piping `jc` converted `ping` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output.
|
||||
See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output.
|
||||
> See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -465,7 +465,7 @@ def _linux_parse(line, s):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -476,13 +476,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -60,12 +60,13 @@ Examples:
|
||||
}
|
||||
]
|
||||
"""
|
||||
from typing import List, Dict, Optional
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`pip show` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -76,7 +77,7 @@ class info():
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data):
|
||||
def _process(proc_data: List[Dict]) -> List[Dict]:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
@@ -92,7 +93,11 @@ def _process(proc_data):
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(data, raw=False, quiet=False):
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
Main text parsing function
|
||||
|
||||
@@ -109,8 +114,10 @@ def parse(data, raw=False, quiet=False):
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
jc.utils.input_type_check(data)
|
||||
|
||||
raw_output = []
|
||||
package = {}
|
||||
raw_output: List = []
|
||||
package: Dict = {}
|
||||
last_key: str = ''
|
||||
last_key_data: List = []
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, data.splitlines()))
|
||||
@@ -119,21 +126,38 @@ def parse(data, raw=False, quiet=False):
|
||||
|
||||
for row in cleandata:
|
||||
if row.startswith('---'):
|
||||
if last_key_data:
|
||||
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
|
||||
|
||||
raw_output.append(package)
|
||||
package = {}
|
||||
last_key = ''
|
||||
last_key_data = []
|
||||
continue
|
||||
|
||||
item_key = row.split(': ', maxsplit=1)[0].lower().replace('-', '_')
|
||||
item_value = row.split(': ', maxsplit=1)[1]
|
||||
if not row.startswith(' '):
|
||||
item_key = row.split(': ', maxsplit=1)[0].lower().replace('-', '_')
|
||||
item_value: Optional[str] = row.split(': ', maxsplit=1)[1]
|
||||
|
||||
if item_value == '':
|
||||
item_value = None
|
||||
if item_value == '':
|
||||
item_value = None
|
||||
|
||||
package.update({item_key: item_value})
|
||||
if last_key_data and last_key != item_key:
|
||||
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
|
||||
last_key_data = []
|
||||
|
||||
raw_output.append(package)
|
||||
package[item_key] = item_value
|
||||
last_key = item_key
|
||||
continue
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return _process(raw_output)
|
||||
if row.startswith(' '):
|
||||
last_key_data.append(row.strip())
|
||||
continue
|
||||
|
||||
if package:
|
||||
if last_key_data:
|
||||
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
|
||||
|
||||
raw_output.append(package)
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
|
||||
@@ -17,20 +17,20 @@ Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"flags_pretty": [
|
||||
string
|
||||
string
|
||||
]
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Works with `rpm -qi [package]` or `rpm -qia`.
|
||||
The `..._epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on)
|
||||
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and is
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and are
|
||||
only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `rsync` command output parser
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -46,8 +46,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -56,7 +56,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""jc - JSON Convert `rsync` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -44,8 +44,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -54,7 +54,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
@@ -80,7 +80,7 @@ Examples:
|
||||
...
|
||||
"""
|
||||
import re
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
@@ -139,9 +139,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -152,13 +152,9 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `ss` command output parser
|
||||
|
||||
Extended information options like -e and -p are not supported and may cause
|
||||
parsing irregularities.
|
||||
Extended information options like `-e` and `-p` are not supported and may
|
||||
cause parsing irregularities.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -18,8 +18,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `stat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on).
|
||||
@@ -127,7 +127,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -138,13 +138,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"""jc - JSON Convert `sysctl -a` command output parser
|
||||
|
||||
Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
key/value object will be output. An attempt is made to convert obvious
|
||||
integers and floats. If no conversion is desired, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
> key/value object will be output. An attempt is made to convert obvious
|
||||
> integers and floats. If no conversion is desired, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ used to redirect the output to a file that can be read by `jc`.
|
||||
Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT`
|
||||
so `jc` can receive it.
|
||||
|
||||
Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
`time` command.
|
||||
> Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
> `time` command.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -21,8 +21,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage,
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
|
||||
{
|
||||
"real_time": float,
|
||||
|
||||
640
jc/parsers/top.py
Normal file
640
jc/parsers/top.py
Normal file
@@ -0,0 +1,640 @@
|
||||
"""jc - JSON Convert `top -b` command output parser
|
||||
|
||||
Requires batch mode (`-b`). The `-n` option must also be used to limit
|
||||
the number of times `top` is run.
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b -n 3 | jc --top
|
||||
|
||||
or
|
||||
|
||||
$ jc top -b -n 3
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('top', top_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
All `-` values are converted to `null`
|
||||
|
||||
[
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b -n 3 | jc --top -p
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": 118,
|
||||
"users": 2,
|
||||
"load_1m": 0.0,
|
||||
"load_5m": 0.01,
|
||||
"load_15m": 0.05,
|
||||
"tasks_total": 108,
|
||||
"tasks_running": 2,
|
||||
"tasks_sleeping": 106,
|
||||
"tasks_stopped": 0,
|
||||
"tasks_zombie": 0,
|
||||
"cpu_user": 5.6,
|
||||
"cpu_sys": 11.1,
|
||||
"cpu_nice": 0.0,
|
||||
"cpu_idle": 83.3,
|
||||
"cpu_wait": 0.0,
|
||||
"cpu_hardware": 0.0,
|
||||
"cpu_software": 0.0,
|
||||
"cpu_steal": 0.0,
|
||||
"mem_total": 3.7,
|
||||
"mem_free": 3.3,
|
||||
"mem_used": 0.2,
|
||||
"mem_buff_cache": 0.2,
|
||||
"swap_total": 2.0,
|
||||
"swap_free": 2.0,
|
||||
"swap_used": 0.0,
|
||||
"mem_available": 3.3,
|
||||
"processes": [
|
||||
{
|
||||
"pid": 2225,
|
||||
"user": "kbrazil",
|
||||
"priority": 20,
|
||||
"nice": 0,
|
||||
"virtual_mem": 158.1,
|
||||
"resident_mem": 2.2,
|
||||
"shared_mem": 1.6,
|
||||
"status": "running",
|
||||
"percent_cpu": 12.5,
|
||||
"percent_mem": 0.1,
|
||||
"time_hundredths": "0:00.02",
|
||||
"command": "top",
|
||||
"parent_pid": 1884,
|
||||
"uid": 1000,
|
||||
"real_uid": 1000,
|
||||
"real_user": "kbrazil",
|
||||
"saved_uid": 1000,
|
||||
"saved_user": "kbrazil",
|
||||
"gid": 1000,
|
||||
"group": "kbrazil",
|
||||
"pgrp": 2225,
|
||||
"tty": "pts/0",
|
||||
"tty_process_gid": 2225,
|
||||
"session_id": 1884,
|
||||
"thread_count": 1,
|
||||
"last_used_processor": 0,
|
||||
"time": "0:00",
|
||||
"swap": 0.0,
|
||||
"code": 0.1,
|
||||
"data": 1.0,
|
||||
"major_page_fault_count": 0,
|
||||
"minor_page_fault_count": 736,
|
||||
"dirty_pages_count": 0,
|
||||
"sleeping_in_function": null,
|
||||
"flags": "..4.2...",
|
||||
"cgroups": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"supplementary_gids": [
|
||||
10,
|
||||
1000
|
||||
],
|
||||
"supplementary_groups": [
|
||||
"wheel",
|
||||
"kbrazil"
|
||||
],
|
||||
"thread_gid": 2225,
|
||||
"environment_variables": [
|
||||
"XDG_SESSION_ID=2",
|
||||
"HOSTNAME=localhost"
|
||||
],
|
||||
"major_page_fault_count_delta": 0,
|
||||
"minor_page_fault_count_delta": 4,
|
||||
"used": 2.2,
|
||||
"ipc_namespace_inode": 4026531839,
|
||||
"mount_namespace_inode": 4026531840,
|
||||
"net_namespace_inode": 4026531956,
|
||||
"pid_namespace_inode": 4026531836,
|
||||
"user_namespace_inode": 4026531837,
|
||||
"nts_namespace_inode": 4026531838
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
$ top -b -n 3 | jc --top -p -r
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": "1:18",
|
||||
"users": "2",
|
||||
"load_1m": "0.00",
|
||||
"load_5m": "0.01",
|
||||
"load_15m": "0.05",
|
||||
"tasks_total": "108",
|
||||
"tasks_running": "2",
|
||||
"tasks_sleeping": "106",
|
||||
"tasks_stopped": "0",
|
||||
"tasks_zombie": "0",
|
||||
"cpu_user": "5.6",
|
||||
"cpu_sys": "11.1",
|
||||
"cpu_nice": "0.0",
|
||||
"cpu_idle": "83.3",
|
||||
"cpu_wait": "0.0",
|
||||
"cpu_hardware": "0.0",
|
||||
"cpu_software": "0.0",
|
||||
"cpu_steal": "0.0",
|
||||
"swap_total": "2.0",
|
||||
"swap_free": "2.0",
|
||||
"swap_used": "0.0",
|
||||
"mem_available": "3.3",
|
||||
"processes": [
|
||||
{
|
||||
"PID": "2225",
|
||||
"USER": "kbrazil",
|
||||
"PR": "20",
|
||||
"NI": "0",
|
||||
"VIRT": "158.1m",
|
||||
"RES": "2.2m",
|
||||
"SHR": "1.6m",
|
||||
"S": "R",
|
||||
"%CPU": "12.5",
|
||||
"%MEM": "0.1",
|
||||
"TIME+": "0:00.02",
|
||||
"COMMAND": "top",
|
||||
"PPID": "1884",
|
||||
"UID": "1000",
|
||||
"RUID": "1000",
|
||||
"RUSER": "kbrazil",
|
||||
"SUID": "1000",
|
||||
"SUSER": "kbrazil",
|
||||
"GID": "1000",
|
||||
"GROUP": "kbrazil",
|
||||
"PGRP": "2225",
|
||||
"TTY": "pts/0",
|
||||
"TPGID": "2225",
|
||||
"SID": "1884",
|
||||
"nTH": "1",
|
||||
"P": "0",
|
||||
"TIME": "0:00",
|
||||
"SWAP": "0.0m",
|
||||
"CODE": "0.1m",
|
||||
"DATA": "1.0m",
|
||||
"nMaj": "0",
|
||||
"nMin": "736",
|
||||
"nDRT": "0",
|
||||
"WCHAN": "-",
|
||||
"Flags": "..4.2...",
|
||||
"CGROUPS": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"SUPGIDS": "10,1000",
|
||||
"SUPGRPS": "wheel,kbrazil",
|
||||
"TGID": "2225",
|
||||
"ENVIRON": "XDG_SESSION_ID=2 HOSTNAME=localhost S+",
|
||||
"vMj": "0",
|
||||
"vMn": "4",
|
||||
"USED": "2.2m",
|
||||
"nsIPC": "4026531839",
|
||||
"nsMNT": "4026531840",
|
||||
"nsNET": "4026531956",
|
||||
"nsPID": "4026531836",
|
||||
"nsUSER": "4026531837",
|
||||
"nsUTS": "4026531838"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
"""
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
from jc.parsers.uptime import parse as parse_uptime
|
||||
from jc.parsers.universal import sparse_table_parse as parse_table
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`top -b` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
magic_commands = ['top -b']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _safe_split(string: str, path: str, delim: str = ' ', quiet=False) -> List[str]:
|
||||
split_string = string.split(delim)
|
||||
split_string = [x for x in split_string if not x.endswith('+')]
|
||||
|
||||
if string.endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'{path} list was truncated by top'])
|
||||
|
||||
return split_string
|
||||
|
||||
|
||||
def _process(proc_data: List[Dict], quiet=False) -> List[Dict]:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
key_map: Dict = {
|
||||
'%CPU': 'percent_cpu',
|
||||
'%MEM': 'percent_mem',
|
||||
'CGNAME': 'control_group_name',
|
||||
'CGROUPS': 'cgroups',
|
||||
'CODE': 'code',
|
||||
'COMMAND': 'command',
|
||||
'DATA': 'data',
|
||||
'ENVIRON': 'environment_variables',
|
||||
'Flags': 'flags',
|
||||
'GID': 'gid',
|
||||
'GROUP': 'group',
|
||||
'LXC': 'lxc_container_name',
|
||||
'NI': 'nice',
|
||||
'NU': 'numa_node',
|
||||
'OOMa': 'out_of_mem_adjustment',
|
||||
'OOMs': 'out_of_mem_score',
|
||||
'P': 'last_used_processor',
|
||||
'PGRP': 'pgrp',
|
||||
'PID': 'pid',
|
||||
'PPID': 'parent_pid',
|
||||
'PR': 'priority',
|
||||
'RES': 'resident_mem',
|
||||
'RSan': 'resident_anon_mem',
|
||||
'RSfd': 'resident_file_backed_mem',
|
||||
'RSlk': 'resident_locked_mem',
|
||||
'RSsh': 'resident_shared_mem',
|
||||
'RUID': 'real_uid',
|
||||
'RUSER': 'real_user',
|
||||
'S': 'status',
|
||||
'SHR': 'shared_mem',
|
||||
'SID': 'session_id',
|
||||
'SUID': 'saved_uid',
|
||||
'SUPGIDS': 'supplementary_gids',
|
||||
'SUPGRPS': 'supplementary_groups',
|
||||
'SUSER': 'saved_user',
|
||||
'SWAP': 'swap',
|
||||
'TGID': 'thread_gid',
|
||||
'TIME': 'time',
|
||||
'TIME+': 'time_hundredths',
|
||||
'TPGID': 'tty_process_gid',
|
||||
'TTY': 'tty',
|
||||
'UID': 'uid',
|
||||
'USED': 'used',
|
||||
'USER': 'user',
|
||||
'VIRT': 'virtual_mem',
|
||||
'WCHAN': 'sleeping_in_function',
|
||||
'nDRT': 'dirty_pages_count',
|
||||
'nMaj': 'major_page_fault_count',
|
||||
'nMin': 'minor_page_fault_count',
|
||||
'nTH': 'thread_count',
|
||||
'nsIPC': 'ipc_namespace_inode',
|
||||
'nsMNT': 'mount_namespace_inode',
|
||||
'nsNET': 'net_namespace_inode',
|
||||
'nsPID': 'pid_namespace_inode',
|
||||
'nsUSER': 'user_namespace_inode',
|
||||
'nsUTS': 'nts_namespace_inode',
|
||||
'vMj': 'major_page_fault_count_delta',
|
||||
'vMn': 'minor_page_fault_count_delta'
|
||||
}
|
||||
|
||||
status_map: Dict = {
|
||||
'D': 'uninterruptible sleep',
|
||||
'I': 'idle',
|
||||
'R': 'running',
|
||||
'S': 'sleeping',
|
||||
'T': 'stopped by job control signal',
|
||||
't': 'stopped by debugger during trace',
|
||||
'Z': 'zombie'
|
||||
}
|
||||
|
||||
int_list: List = [
|
||||
'uptime', 'users', 'tasks_total', 'tasks_running', 'tasks_sleeping', 'tasks_stopped',
|
||||
'tasks_zombie', 'pid', 'priority', 'nice', 'parent_pid', 'uid', 'real_uid', 'saved_uid',
|
||||
'gid', 'pgrp', 'tty_process_gid', 'session_id', 'thread_count', 'last_used_processor',
|
||||
'major_page_fault_count', 'minor_page_fault_count', 'dirty_pages_count', 'thread_gid',
|
||||
'major_page_fault_count_delta', 'minor_page_fault_count_delta', 'ipc_namespace_inode',
|
||||
'mount_namespace_inode', 'net_namespace_inode', 'pid_namespace_inode',
|
||||
'user_namespace_inode', 'nts_namespace_inode', 'numa_node', 'out_of_mem_adjustment',
|
||||
'out_of_mem_score', 'resident_anon_mem', 'resident_file_backed_mem', 'resident_locked_mem',
|
||||
'resident_shared_mem'
|
||||
]
|
||||
|
||||
float_list: List = [
|
||||
'load_1m', 'load_5m', 'load_15m', 'cpu_user', 'cpu_sys', 'cpu_nice', 'cpu_idle', 'cpu_wait',
|
||||
'cpu_hardware', 'cpu_software', 'cpu_steal', 'percent_cpu', 'percent_mem', 'mem_total',
|
||||
'mem_free', 'mem_used', 'mem_buff_cache', 'swap_total', 'swap_free', 'swap_used',
|
||||
'mem_available', 'virtual_mem', 'resident_mem', 'shared_mem', 'swap', 'code', 'data', 'used'
|
||||
]
|
||||
|
||||
for idx, item in enumerate(proc_data):
|
||||
for key in item:
|
||||
# root truncation warnings
|
||||
if isinstance(item[key], str) and item[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["{key}"] was truncated by top'])
|
||||
|
||||
# root int and float conversions
|
||||
if key in int_list:
|
||||
item[key] = jc.utils.convert_to_int(item[key])
|
||||
|
||||
if key in float_list:
|
||||
item[key] = jc.utils.convert_to_float(item[key])
|
||||
|
||||
for p_idx, proc in enumerate(item['processes']):
|
||||
# rename processes keys to conform to schema
|
||||
proc_copy = proc.copy()
|
||||
for old_key in proc_copy.keys():
|
||||
if old_key in proc:
|
||||
proc[key_map[old_key]] = proc.pop(old_key)
|
||||
else:
|
||||
jc.utils.warning_message([f'Unknown field detected at item[{idx}]["processes"]: {old_key}'])
|
||||
|
||||
# cleanup values
|
||||
for key in proc.keys():
|
||||
|
||||
# set dashes to nulls
|
||||
if proc[key] == '-':
|
||||
proc[key] = None
|
||||
|
||||
# because of ambiguous column spacing (right-justified numbers
|
||||
# with left-justified dashes for null values) there are some hanging
|
||||
# dashes that need to be cleaned up in some values. Seems the correct
|
||||
# values are kept in the assigned columns, so this should not affect
|
||||
# data integrity.
|
||||
if proc[key] and proc[key].endswith(' -'):
|
||||
new_val = proc[key][::-1]
|
||||
new_val = new_val.replace('- ', '')
|
||||
new_val = new_val[::-1]
|
||||
proc[key] = new_val
|
||||
|
||||
# do int/float conversions for the process objects
|
||||
if proc[key]:
|
||||
if key in int_list:
|
||||
proc[key] = jc.utils.convert_to_int(proc[key])
|
||||
|
||||
if key in float_list:
|
||||
proc[key] = jc.utils.convert_to_float(proc[key])
|
||||
|
||||
# set status string
|
||||
if proc.get('status'):
|
||||
proc['status'] = status_map[proc['status']]
|
||||
|
||||
# split supplementary_gids to a list of integers
|
||||
if proc.get('supplementary_gids'):
|
||||
proc['supplementary_gids'] = _safe_split(
|
||||
proc['supplementary_gids'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_gids"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
proc['supplementary_gids'] = [jc.utils.convert_to_int(x) for x in proc['supplementary_gids']]
|
||||
|
||||
# split supplementary_groups to a list of strings
|
||||
if proc.get('supplementary_groups'):
|
||||
proc['supplementary_groups'] = _safe_split(
|
||||
proc['supplementary_groups'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_groups"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
# split environment_variables to a list of strings
|
||||
if proc.get('environment_variables'):
|
||||
proc['environment_variables'] = _safe_split(
|
||||
proc['environment_variables'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["environment_variables"]',
|
||||
quiet=quiet
|
||||
)
|
||||
|
||||
for key in proc.keys():
|
||||
# print final warnings for truncated string values
|
||||
if isinstance(proc[key], str) and proc[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["processes"][{p_idx}]["{key}"] was truncated by top'])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
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 = []
|
||||
item_obj: Dict = {}
|
||||
process_table = False
|
||||
process_list: List = []
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
for line in data.splitlines():
|
||||
if line.startswith('top - '):
|
||||
if item_obj:
|
||||
if process_list:
|
||||
item_obj['processes'] = parse_table(process_list)
|
||||
raw_output.append(item_obj)
|
||||
process_table = False
|
||||
process_list = []
|
||||
item_obj = {}
|
||||
|
||||
uptime_str = line[6:]
|
||||
item_obj.update(parse_uptime(uptime_str, raw=True))
|
||||
continue
|
||||
|
||||
if line.startswith('Tasks:'):
|
||||
# Tasks: 112 total, 1 running, 111 sleeping, 0 stopped, 0 zombie
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'tasks_total': line_list[1],
|
||||
'tasks_running': line_list[3],
|
||||
'tasks_sleeping': line_list[5],
|
||||
'tasks_stopped': line_list[7],
|
||||
'tasks_zombie': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line.startswith('%Cpu(s):'):
|
||||
# %Cpu(s): 5.9 us, 5.9 sy, 0.0 ni, 88.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'cpu_user': line_list[1],
|
||||
'cpu_sys': line_list[3],
|
||||
'cpu_nice': line_list[5],
|
||||
'cpu_idle': line_list[7],
|
||||
'cpu_wait': line_list[9],
|
||||
'cpu_hardware': line_list[11],
|
||||
'cpu_software': line_list[13],
|
||||
'cpu_steal': line_list[15]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Mem :'):
|
||||
# KiB Mem : 3861332 total, 3446476 free, 216940 used, 197916 buff/cache
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'mem_total': line_list[3],
|
||||
'mem_free': line_list[5],
|
||||
'mem_used': line_list[7],
|
||||
'mem_buff_cache': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Swap:'):
|
||||
# KiB Swap: 2097148 total, 2097148 free, 0 used. 3419356 avail Mem
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'swap_total': line_list[2],
|
||||
'swap_free': line_list[4],
|
||||
'swap_used': line_list[6],
|
||||
'mem_available': line_list[8]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if not process_table and line == '':
|
||||
process_table = True
|
||||
continue
|
||||
|
||||
if process_table and not line == '':
|
||||
process_list.append(line)
|
||||
continue
|
||||
|
||||
if item_obj:
|
||||
if process_list:
|
||||
item_obj['processes'] = parse_table(process_list)
|
||||
raw_output.append(item_obj)
|
||||
|
||||
return raw_output if raw else _process(raw_output, quiet=quiet)
|
||||
490
jc/parsers/top_s.py
Normal file
490
jc/parsers/top_s.py
Normal file
@@ -0,0 +1,490 @@
|
||||
"""jc - JSON Convert `top -b` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires batch mode (`-b`).
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b | jc --top-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('top_s', top_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
],
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b | jc --top-s
|
||||
{"time":"11:24:50","uptime":2,"users":2,"load_1m":0.23,"load_5m":...}
|
||||
...
|
||||
|
||||
$ top -b | jc --top-s -r
|
||||
{"time":"11:24:50","uptime":"2 min","users":"2","load_1m":"0.23","lo...}
|
||||
...
|
||||
"""
|
||||
from typing import List, Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
)
|
||||
from jc.exceptions import ParseError
|
||||
from jc.parsers.uptime import parse as parse_uptime
|
||||
from jc.parsers.universal import sparse_table_parse as parse_table
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`top -b` command streaming parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
streaming = True
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _safe_split(string: str, path: str, delim: str = ' ', quiet=False) -> List[str]:
|
||||
split_string = string.split(delim)
|
||||
split_string = [x for x in split_string if not x.endswith('+')]
|
||||
|
||||
if string.endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'{path} list was truncated by top'])
|
||||
|
||||
return split_string
|
||||
|
||||
|
||||
def _process(proc_data: Dict, idx=0, quiet=False) -> Dict:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
key_map: Dict = {
|
||||
'%CPU': 'percent_cpu',
|
||||
'%MEM': 'percent_mem',
|
||||
'CGNAME': 'control_group_name',
|
||||
'CGROUPS': 'cgroups',
|
||||
'CODE': 'code',
|
||||
'COMMAND': 'command',
|
||||
'DATA': 'data',
|
||||
'ENVIRON': 'environment_variables',
|
||||
'Flags': 'flags',
|
||||
'GID': 'gid',
|
||||
'GROUP': 'group',
|
||||
'LXC': 'lxc_container_name',
|
||||
'NI': 'nice',
|
||||
'NU': 'numa_node',
|
||||
'OOMa': 'out_of_mem_adjustment',
|
||||
'OOMs': 'out_of_mem_score',
|
||||
'P': 'last_used_processor',
|
||||
'PGRP': 'pgrp',
|
||||
'PID': 'pid',
|
||||
'PPID': 'parent_pid',
|
||||
'PR': 'priority',
|
||||
'RES': 'resident_mem',
|
||||
'RSan': 'resident_anon_mem',
|
||||
'RSfd': 'resident_file_backed_mem',
|
||||
'RSlk': 'resident_locked_mem',
|
||||
'RSsh': 'resident_shared_mem',
|
||||
'RUID': 'real_uid',
|
||||
'RUSER': 'real_user',
|
||||
'S': 'status',
|
||||
'SHR': 'shared_mem',
|
||||
'SID': 'session_id',
|
||||
'SUID': 'saved_uid',
|
||||
'SUPGIDS': 'supplementary_gids',
|
||||
'SUPGRPS': 'supplementary_groups',
|
||||
'SUSER': 'saved_user',
|
||||
'SWAP': 'swap',
|
||||
'TGID': 'thread_gid',
|
||||
'TIME': 'time',
|
||||
'TIME+': 'time_hundredths',
|
||||
'TPGID': 'tty_process_gid',
|
||||
'TTY': 'tty',
|
||||
'UID': 'uid',
|
||||
'USED': 'used',
|
||||
'USER': 'user',
|
||||
'VIRT': 'virtual_mem',
|
||||
'WCHAN': 'sleeping_in_function',
|
||||
'nDRT': 'dirty_pages_count',
|
||||
'nMaj': 'major_page_fault_count',
|
||||
'nMin': 'minor_page_fault_count',
|
||||
'nTH': 'thread_count',
|
||||
'nsIPC': 'ipc_namespace_inode',
|
||||
'nsMNT': 'mount_namespace_inode',
|
||||
'nsNET': 'net_namespace_inode',
|
||||
'nsPID': 'pid_namespace_inode',
|
||||
'nsUSER': 'user_namespace_inode',
|
||||
'nsUTS': 'nts_namespace_inode',
|
||||
'vMj': 'major_page_fault_count_delta',
|
||||
'vMn': 'minor_page_fault_count_delta'
|
||||
}
|
||||
|
||||
status_map: Dict = {
|
||||
'D': 'uninterruptible sleep',
|
||||
'I': 'idle',
|
||||
'R': 'running',
|
||||
'S': 'sleeping',
|
||||
'T': 'stopped by job control signal',
|
||||
't': 'stopped by debugger during trace',
|
||||
'Z': 'zombie'
|
||||
}
|
||||
|
||||
int_list: List = [
|
||||
'uptime', 'users', 'tasks_total', 'tasks_running', 'tasks_sleeping', 'tasks_stopped',
|
||||
'tasks_zombie', 'pid', 'priority', 'nice', 'parent_pid', 'uid', 'real_uid', 'saved_uid',
|
||||
'gid', 'pgrp', 'tty_process_gid', 'session_id', 'thread_count', 'last_used_processor',
|
||||
'major_page_fault_count', 'minor_page_fault_count', 'dirty_pages_count', 'thread_gid',
|
||||
'major_page_fault_count_delta', 'minor_page_fault_count_delta', 'ipc_namespace_inode',
|
||||
'mount_namespace_inode', 'net_namespace_inode', 'pid_namespace_inode',
|
||||
'user_namespace_inode', 'nts_namespace_inode', 'numa_node', 'out_of_mem_adjustment',
|
||||
'out_of_mem_score', 'resident_anon_mem', 'resident_file_backed_mem', 'resident_locked_mem',
|
||||
'resident_shared_mem'
|
||||
]
|
||||
|
||||
float_list: List = [
|
||||
'load_1m', 'load_5m', 'load_15m', 'cpu_user', 'cpu_sys', 'cpu_nice', 'cpu_idle', 'cpu_wait',
|
||||
'cpu_hardware', 'cpu_software', 'cpu_steal', 'percent_cpu', 'percent_mem', 'mem_total',
|
||||
'mem_free', 'mem_used', 'mem_buff_cache', 'swap_total', 'swap_free', 'swap_used',
|
||||
'mem_available', 'virtual_mem', 'resident_mem', 'shared_mem', 'swap', 'code', 'data', 'used'
|
||||
]
|
||||
|
||||
for key in proc_data:
|
||||
# root truncation warnings
|
||||
if isinstance(proc_data[key], str) and proc_data[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["{key}"] was truncated by top'])
|
||||
|
||||
# root int and float conversions
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
|
||||
if key in float_list:
|
||||
proc_data[key] = jc.utils.convert_to_float(proc_data[key])
|
||||
|
||||
for p_idx, proc in enumerate(proc_data['processes']):
|
||||
# rename processes keys to conform to schema
|
||||
proc_copy = proc.copy()
|
||||
for old_key in proc_copy.keys():
|
||||
if old_key in proc:
|
||||
proc[key_map[old_key]] = proc.pop(old_key)
|
||||
else:
|
||||
jc.utils.warning_message([f'Unknown field detected at item[{idx}]["processes"]: {old_key}'])
|
||||
|
||||
# cleanup values
|
||||
for key in proc.keys():
|
||||
|
||||
# set dashes to nulls
|
||||
if proc[key] == '-':
|
||||
proc[key] = None
|
||||
|
||||
# because of ambiguous column spacing (right-justified numbers
|
||||
# with left-justified dashes for null values) there are some hanging
|
||||
# dashes that need to be cleaned up in some values. Seems the correct
|
||||
# values are kept in the assigned columns, so this should not affect
|
||||
# data integrity.
|
||||
if proc[key] and proc[key].endswith(' -'):
|
||||
new_val = proc[key][::-1]
|
||||
new_val = new_val.replace('- ', '')
|
||||
new_val = new_val[::-1]
|
||||
proc[key] = new_val
|
||||
|
||||
# do int/float conversions for the process objects
|
||||
if proc[key]:
|
||||
if key in int_list:
|
||||
proc[key] = jc.utils.convert_to_int(proc[key])
|
||||
|
||||
if key in float_list:
|
||||
proc[key] = jc.utils.convert_to_float(proc[key])
|
||||
|
||||
# set status string
|
||||
if proc.get('status'):
|
||||
proc['status'] = status_map[proc['status']]
|
||||
|
||||
# split supplementary_gids to a list of integers
|
||||
if proc.get('supplementary_gids'):
|
||||
proc['supplementary_gids'] = _safe_split(
|
||||
proc['supplementary_gids'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_gids"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
proc['supplementary_gids'] = [jc.utils.convert_to_int(x) for x in proc['supplementary_gids']]
|
||||
|
||||
# split supplementary_groups to a list of strings
|
||||
if proc.get('supplementary_groups'):
|
||||
proc['supplementary_groups'] = _safe_split(
|
||||
proc['supplementary_groups'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_groups"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
# split environment_variables to a list of strings
|
||||
if proc.get('environment_variables'):
|
||||
proc['environment_variables'] = _safe_split(
|
||||
proc['environment_variables'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["environment_variables"]',
|
||||
quiet=quiet
|
||||
)
|
||||
|
||||
for key in proc.keys():
|
||||
# print final warnings for truncated string values
|
||||
if isinstance(proc[key], str) and proc[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["processes"][{p_idx}]["{key}"] was truncated by top'])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
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)
|
||||
|
||||
output_line: Dict = {}
|
||||
process_table = False
|
||||
process_list: List = []
|
||||
idx = 0
|
||||
|
||||
for line in data:
|
||||
try:
|
||||
streaming_line_input_type_check(line)
|
||||
|
||||
if line.startswith('top - '):
|
||||
if output_line:
|
||||
if process_list:
|
||||
output_line['processes'] = parse_table(process_list)
|
||||
yield output_line if raw else _process(output_line, idx=idx, quiet=quiet)
|
||||
process_table = False
|
||||
process_list = []
|
||||
output_line = {}
|
||||
idx += 1
|
||||
|
||||
uptime_str = line[6:]
|
||||
output_line.update(parse_uptime(uptime_str, raw=True))
|
||||
continue
|
||||
|
||||
if line.startswith('Tasks:'):
|
||||
# Tasks: 112 total, 1 running, 111 sleeping, 0 stopped, 0 zombie
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'tasks_total': line_list[1],
|
||||
'tasks_running': line_list[3],
|
||||
'tasks_sleeping': line_list[5],
|
||||
'tasks_stopped': line_list[7],
|
||||
'tasks_zombie': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line.startswith('%Cpu(s):'):
|
||||
# %Cpu(s): 5.9 us, 5.9 sy, 0.0 ni, 88.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'cpu_user': line_list[1],
|
||||
'cpu_sys': line_list[3],
|
||||
'cpu_nice': line_list[5],
|
||||
'cpu_idle': line_list[7],
|
||||
'cpu_wait': line_list[9],
|
||||
'cpu_hardware': line_list[11],
|
||||
'cpu_software': line_list[13],
|
||||
'cpu_steal': line_list[15]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Mem :'):
|
||||
# KiB Mem : 3861332 total, 3446476 free, 216940 used, 197916 buff/cache
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'mem_total': line_list[3],
|
||||
'mem_free': line_list[5],
|
||||
'mem_used': line_list[7],
|
||||
'mem_buff_cache': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Swap:'):
|
||||
# KiB Swap: 2097148 total, 2097148 free, 0 used. 3419356 avail Mem
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'swap_total': line_list[2],
|
||||
'swap_free': line_list[4],
|
||||
'swap_used': line_list[6],
|
||||
'mem_available': line_list[8]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if not process_table and line.rstrip() == '':
|
||||
process_table = True
|
||||
continue
|
||||
|
||||
if process_table and not line.rstrip() == '':
|
||||
process_list.append(line.rstrip())
|
||||
continue
|
||||
|
||||
if process_table and line.rstrip() == '':
|
||||
continue
|
||||
|
||||
raise ParseError('Not top data')
|
||||
|
||||
except Exception as e:
|
||||
yield raise_or_yield(ignore_exceptions, e, line)
|
||||
|
||||
if output_line:
|
||||
if process_list:
|
||||
output_line['processes'] = parse_table(process_list)
|
||||
yield output_line if raw else _process(output_line, idx=idx, quiet=quiet)
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
Supports `traceroute` and `traceroute6` output.
|
||||
|
||||
Note: On some operating systems you will need to redirect `STDERR` to
|
||||
`STDOUT` for destination info since the header line is sent to
|
||||
`STDERR`. A warning message will be printed to `STDERR` if the
|
||||
header row is not found.
|
||||
|
||||
e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
> Note: On some operating systems you will need to redirect `STDERR` to
|
||||
> `STDOUT` for destination info since the header line is sent to
|
||||
> `STDERR`. A warning message will be printed to `STDERR` if the
|
||||
> header row is not found.
|
||||
>
|
||||
> e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `uname -a` command output parser
|
||||
|
||||
Note: Must use `uname -a`
|
||||
> Note: Must use `uname -a`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
111
jc/parsers/update_alt_gs.py
Normal file
111
jc/parsers/update_alt_gs.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""jc - JSON Convert `update-alternatives --get-selections` command output parser
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ update-alternatives --get-selections | jc --update-alt-gs
|
||||
|
||||
or
|
||||
|
||||
$ jc update-alternatives --get-selections
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('update-alt-gs',
|
||||
update_alternatives_get_selections_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"name": string,
|
||||
"status": string,
|
||||
"current": string
|
||||
}
|
||||
]
|
||||
|
||||
Examples:
|
||||
|
||||
$ update-alternatives --get-selections | jc --update-alt-gs -p
|
||||
[
|
||||
{
|
||||
"name": "arptables",
|
||||
"status": "auto",
|
||||
"current": "/usr/sbin/arptables-nft"
|
||||
},
|
||||
{
|
||||
"name": "awk",
|
||||
"status": "auto",
|
||||
"current": "/usr/bin/gawk"
|
||||
}
|
||||
]
|
||||
"""
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`update-alternatives --get-selections` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
magic_commands = ['update-alternatives --get-selections']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: List[Dict]) -> List[Dict]:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
# nothing to process
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
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 = []
|
||||
output_line = {}
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
for line in filter(None, data.splitlines()):
|
||||
line_list = line.split(maxsplit=2)
|
||||
output_line = {
|
||||
"name": line_list[0],
|
||||
"status": line_list[1],
|
||||
"current": line_list[2]
|
||||
}
|
||||
raw_output.append(output_line)
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
263
jc/parsers/update_alt_q.py
Normal file
263
jc/parsers/update_alt_q.py
Normal file
@@ -0,0 +1,263 @@
|
||||
"""jc - JSON Convert `update-alternatives --query` command output parser
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ update-alternatives --query | jc --update-alt-q
|
||||
|
||||
or
|
||||
|
||||
$ jc update-alternatives --query
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('update_alt_q',
|
||||
update_alternatives_query_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"name": string,
|
||||
"link": string,
|
||||
"slaves": [
|
||||
{
|
||||
"name": string,
|
||||
"path": string
|
||||
}
|
||||
],
|
||||
"status": string,
|
||||
"best": string,
|
||||
"value": string, # (null if 'none')
|
||||
"alternatives": [
|
||||
{
|
||||
"alternative": string,
|
||||
"priority": integer,
|
||||
"slaves": [
|
||||
{
|
||||
"name": string,
|
||||
"path": string
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ update-alternatives --query editor | jc --update-alt-q -p
|
||||
{
|
||||
"name": "editor",
|
||||
"link": "/usr/bin/editor",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/editor.1.gz"
|
||||
},
|
||||
{
|
||||
"name": "editor.da.1.gz",
|
||||
"path": "/usr/share/man/da/man1/editor.1.gz"
|
||||
}
|
||||
],
|
||||
"status": "auto",
|
||||
"best": "/bin/nano",
|
||||
"value": "/bin/nano",
|
||||
"alternatives": [
|
||||
{
|
||||
"alternative": "/bin/ed",
|
||||
"priority": -100,
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/ed.1.gz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alternative": "/bin/nano",
|
||||
"priority": 40,
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/nano.1.gz"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$ update-alternatives --query | jc --update-alt-q -p -r
|
||||
{
|
||||
"name": "editor",
|
||||
"link": "/usr/bin/editor",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/editor.1.gz"
|
||||
},
|
||||
{
|
||||
"name": "editor.da.1.gz",
|
||||
"path": "/usr/share/man/da/man1/editor.1.gz"
|
||||
}
|
||||
],
|
||||
"status": "auto",
|
||||
"best": "/bin/nano",
|
||||
"value": "/bin/nano",
|
||||
"alternatives": [
|
||||
{
|
||||
"alternative": "/bin/ed",
|
||||
"priority": "-100",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/ed.1.gz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alternative": "/bin/nano",
|
||||
"priority": "40",
|
||||
"slaves": [
|
||||
{
|
||||
"name": "editor.1.gz",
|
||||
"path": "/usr/share/man/man1/nano.1.gz"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
description = '`update-alternatives --query` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
magic_commands = ['update-alternatives --query']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: Dict) -> Dict:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (Dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured to conform to the schema.
|
||||
"""
|
||||
int_list = ['priority']
|
||||
|
||||
if 'value' in proc_data:
|
||||
if proc_data['value'] == 'none':
|
||||
proc_data['value'] = None
|
||||
|
||||
if 'alternatives' in proc_data:
|
||||
for index, alt in enumerate(proc_data['alternatives']):
|
||||
for key in alt:
|
||||
if key in int_list:
|
||||
proc_data['alternatives'][index][key] = jc.utils.convert_to_int(proc_data['alternatives'][index][key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> Dict:
|
||||
"""
|
||||
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: Dict = {}
|
||||
slaves: List = []
|
||||
alt_obj: Dict = {}
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
for line in filter(None, data.splitlines()):
|
||||
line_list = line.split(maxsplit=1)
|
||||
|
||||
if line.startswith('Name: '):
|
||||
raw_output['name'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Link: '):
|
||||
raw_output['link'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Slaves:'):
|
||||
continue
|
||||
|
||||
if line.startswith(' '):
|
||||
s_name = line_list[0].strip()
|
||||
s_path = line_list[1]
|
||||
slaves.append(
|
||||
{
|
||||
"name": s_name,
|
||||
"path": s_path
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line.startswith('Status: '):
|
||||
if slaves:
|
||||
raw_output['slaves'] = slaves
|
||||
slaves = []
|
||||
raw_output['status'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Best: '):
|
||||
raw_output['best'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Value: '):
|
||||
raw_output['value'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Alternative: '):
|
||||
if not 'alternatives' in raw_output:
|
||||
raw_output['alternatives'] = []
|
||||
|
||||
if alt_obj:
|
||||
if slaves:
|
||||
alt_obj['slaves'] = slaves
|
||||
slaves = []
|
||||
|
||||
raw_output['alternatives'].append(alt_obj)
|
||||
|
||||
alt_obj = {"alternative": line_list[1]}
|
||||
continue
|
||||
|
||||
if line.startswith('Priority: '):
|
||||
alt_obj['priority'] = line_list[1]
|
||||
continue
|
||||
|
||||
if alt_obj:
|
||||
if slaves:
|
||||
alt_obj['slaves'] = slaves
|
||||
raw_output['alternatives'].append(alt_obj)
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `vmstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Options supported: `-a`, `-w`, `-d`, `-t`
|
||||
|
||||
@@ -16,11 +16,11 @@ Usage (cli):
|
||||
$ vmstat | jc --vmstat-s
|
||||
|
||||
> Note: When piping `jc` converted `vmstat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -70,9 +70,9 @@ Schema:
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -158,13 +158,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -11,8 +11,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
XML Document converted to a Dictionary
|
||||
See https://github.com/martinblech/xmltodict for details
|
||||
XML Document converted to a Dictionary. See https://github.com/martinblech/xmltodict
|
||||
for details.
|
||||
|
||||
{
|
||||
"key1": string/object,
|
||||
|
||||
@@ -49,7 +49,8 @@ Schema:
|
||||
"offset_width": integer,
|
||||
"offset_height": integer,
|
||||
"dimension_width": integer,
|
||||
"dimension_height": integer
|
||||
"dimension_height": integer,
|
||||
"rotation": string
|
||||
}
|
||||
],
|
||||
"unassociated_devices": [
|
||||
@@ -125,7 +126,8 @@ Examples:
|
||||
"offset_width": 0,
|
||||
"offset_height": 0,
|
||||
"dimension_width": 310,
|
||||
"dimension_height": 170
|
||||
"dimension_height": 170,
|
||||
"rotation": "normal"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -140,7 +142,7 @@ import jc.utils
|
||||
class info:
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
|
||||
version = "1.0"
|
||||
version = "1.1"
|
||||
description = "`xrandr` command parser"
|
||||
author = "Kevin Lyter"
|
||||
author_email = "lyter_git at sent.com"
|
||||
@@ -252,6 +254,7 @@ _device_pattern = (
|
||||
+ "(?P<is_primary> primary)? ?"
|
||||
+ "((?P<resolution_width>\d+)x(?P<resolution_height>\d+)"
|
||||
+ "\+(?P<offset_width>\d+)\+(?P<offset_height>\d+))? "
|
||||
+ "(?P<rotation>(inverted|left|right))? ?"
|
||||
+ "\(normal left inverted right x axis y axis\)"
|
||||
+ "( ((?P<dimension_width>\d+)mm x (?P<dimension_height>\d+)mm)?)?"
|
||||
)
|
||||
@@ -275,9 +278,10 @@ def _parse_device(next_lines: List[str], quiet: bool = False) -> Optional[Device
|
||||
"is_primary": matches["is_primary"] is not None
|
||||
and len(matches["is_primary"]) > 0,
|
||||
"device_name": matches["device_name"],
|
||||
"rotation": matches["rotation"] or "normal",
|
||||
}
|
||||
for k, v in matches.items():
|
||||
if k not in {"is_connected", "is_primary", "device_name"}:
|
||||
if k not in {"is_connected", "is_primary", "device_name", "rotation"}:
|
||||
try:
|
||||
if v:
|
||||
device[k] = int(v)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""jc - JSON Convert `YAML` file parser
|
||||
|
||||
> Note: `datetime` objects will be converted to strings.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat foo.yaml | jc --yaml
|
||||
@@ -85,7 +87,7 @@ from jc.exceptions import LibraryNotInstalled
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.6'
|
||||
version = '1.7'
|
||||
description = 'YAML file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -147,6 +149,11 @@ def parse(data, raw=False, quiet=False):
|
||||
|
||||
yaml = YAML(typ='safe')
|
||||
|
||||
# modify the timestamp constructor to output datetime objects as
|
||||
# strings since JSON does not support datetime objects
|
||||
yaml.constructor.yaml_constructors['tag:yaml.org,2002:timestamp'] = \
|
||||
yaml.constructor.yaml_constructors['tag:yaml.org,2002:str']
|
||||
|
||||
for document in yaml.load_all(data):
|
||||
raw_output.append(document)
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"""jc - JSON Convert `zipinfo` command output parser
|
||||
|
||||
Options supported:
|
||||
- none
|
||||
|
||||
Note: The default listing format.
|
||||
> Note: No `zipinfo` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
81
jc/utils.py
81
jc/utils.py
@@ -6,13 +6,33 @@ import shutil
|
||||
from datetime import datetime, timezone
|
||||
from textwrap import TextWrapper
|
||||
from functools import lru_cache
|
||||
from typing import List, Tuple, Union, Optional
|
||||
from typing import List, Iterable, Union, Optional
|
||||
|
||||
|
||||
def _asciify(string: str) -> str:
|
||||
"""
|
||||
Return a string downgraded from Unicode to ASCII with some simple
|
||||
conversions.
|
||||
"""
|
||||
string = string.replace('©', '(c)')
|
||||
# the ascii() function adds single quotes around the string
|
||||
string = ascii(string)[1:-1]
|
||||
string = string.replace(r'\n', '\n')
|
||||
return string
|
||||
|
||||
|
||||
def _safe_print(string: str, sep=' ', end='\n', file=sys.stdout, flush=False) -> None:
|
||||
"""Output for both UTF-8 and ASCII encoding systems"""
|
||||
try:
|
||||
print(string, sep=sep, end=end, file=file, flush=flush)
|
||||
except UnicodeEncodeError:
|
||||
print(_asciify(string), sep=sep, end=end, file=file, flush=flush)
|
||||
|
||||
|
||||
def warning_message(message_lines: List[str]) -> None:
|
||||
"""
|
||||
Prints warning message for non-fatal issues. The first line is
|
||||
prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Prints warning message to `STDERR` for non-fatal issues. The first line
|
||||
is prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
Parameters:
|
||||
@@ -36,18 +56,18 @@ def warning_message(message_lines: List[str]) -> None:
|
||||
first_line = message_lines.pop(0)
|
||||
first_str = f'jc: Warning - {first_line}'
|
||||
first_str = first_wrapper.fill(first_str)
|
||||
print(first_str, file=sys.stderr)
|
||||
_safe_print(first_str, file=sys.stderr)
|
||||
|
||||
for line in message_lines:
|
||||
if line == '':
|
||||
continue
|
||||
message = next_wrapper.fill(line)
|
||||
print(message, file=sys.stderr)
|
||||
_safe_print(message, file=sys.stderr)
|
||||
|
||||
|
||||
def error_message(message_lines: List[str]) -> None:
|
||||
"""
|
||||
Prints an error message for fatal issues. The first line is
|
||||
Prints an error message to `STDERR` for fatal issues. The first line is
|
||||
prepended with 'jc: Error - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
@@ -68,19 +88,33 @@ def error_message(message_lines: List[str]) -> None:
|
||||
first_line = message_lines.pop(0)
|
||||
first_str = f'jc: Error - {first_line}'
|
||||
first_str = first_wrapper.fill(first_str)
|
||||
print(first_str, file=sys.stderr)
|
||||
_safe_print(first_str, file=sys.stderr)
|
||||
|
||||
for line in message_lines:
|
||||
if line == '':
|
||||
continue
|
||||
message = next_wrapper.fill(line)
|
||||
print(message, file=sys.stderr)
|
||||
_safe_print(message, file=sys.stderr)
|
||||
|
||||
|
||||
def is_compatible(compatible: List) -> bool:
|
||||
"""
|
||||
Returns True if the parser is compatible with the running OS platform.
|
||||
"""
|
||||
platform_found = False
|
||||
|
||||
for platform in compatible:
|
||||
if sys.platform.startswith(platform):
|
||||
platform_found = True
|
||||
break
|
||||
|
||||
return platform_found
|
||||
|
||||
|
||||
def compatibility(mod_name: str, compatible: List, quiet: bool = False) -> None:
|
||||
"""
|
||||
Checks for the parser's compatibility with the running OS
|
||||
platform.
|
||||
Checks for the parser's compatibility with the running OS platform and
|
||||
prints a warning message to `STDERR` if not compatible and quiet=False.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -96,21 +130,13 @@ def compatibility(mod_name: str, compatible: List, quiet: bool = False) -> None:
|
||||
|
||||
None - just prints output to STDERR
|
||||
"""
|
||||
if not quiet:
|
||||
platform_found = False
|
||||
|
||||
for platform in compatible:
|
||||
if sys.platform.startswith(platform):
|
||||
platform_found = True
|
||||
break
|
||||
|
||||
if not platform_found:
|
||||
mod = mod_name.split('.')[-1]
|
||||
compat_list = ', '.join(compatible)
|
||||
warning_message([
|
||||
f'{mod} parser is not compatible with your OS ({sys.platform}).',
|
||||
f'Compatible platforms: {compat_list}'
|
||||
])
|
||||
if not quiet and not is_compatible(compatible):
|
||||
mod = mod_name.split('.')[-1]
|
||||
compat_list = ', '.join(compatible)
|
||||
warning_message([
|
||||
f'{mod} parser is not compatible with your OS ({sys.platform}).',
|
||||
f'Compatible platforms: {compat_list}'
|
||||
])
|
||||
|
||||
|
||||
def has_data(data: str) -> bool:
|
||||
@@ -233,7 +259,7 @@ def input_type_check(data: str) -> None:
|
||||
class timestamp:
|
||||
def __init__(self,
|
||||
datetime_string: str,
|
||||
format_hint: Union[List, Tuple, None] = None
|
||||
format_hint: Optional[Iterable] = None
|
||||
) -> None:
|
||||
"""
|
||||
Input a datetime text string of several formats and convert to a
|
||||
@@ -244,7 +270,7 @@ class timestamp:
|
||||
datetime_string (str): a string representation of a
|
||||
datetime in several supported formats
|
||||
|
||||
format_hint (list | tuple): an optional list of format ID
|
||||
format_hint (iterable): an optional iterable of format ID
|
||||
integers to instruct the timestamp object to try those
|
||||
formats first in the order given. Other formats will be
|
||||
tried after the format hint list is exhausted. This can
|
||||
@@ -361,6 +387,7 @@ class timestamp:
|
||||
|
||||
formats = [
|
||||
{'id': 1000, 'format': '%a %b %d %H:%M:%S %Y', 'locale': None}, # manual C locale format conversion: Tue Mar 23 16:12:11 2021 or Tue Mar 23 16:12:11 IST 2021
|
||||
{'id': 1100, 'format': '%a %b %d %H:%M:%S %Y %z', 'locale': None}, # git date output: Thu Mar 5 09:17:40 2020 -0800
|
||||
{'id': 1500, 'format': '%Y-%m-%d %H:%M', 'locale': None}, # en_US.UTF-8 local format (found in who cli output): 2021-03-23 00:14
|
||||
{'id': 1600, 'format': '%m/%d/%Y %I:%M %p', 'locale': None}, # Windows english format (found in dir cli output): 12/07/2019 02:09 AM
|
||||
{'id': 1700, 'format': '%m/%d/%Y, %I:%M:%S %p', 'locale': None}, # Windows english format wint non-UTC tz (found in systeminfo cli output): 3/22/2021, 1:15:51 PM (UTC-0600)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user