1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-17 01:32:37 +02:00

Merge pull request #655 from kellyjonbrazil/dev

Dev v1.25.5
This commit is contained in:
Kelly Brazil
2025-05-10 11:38:04 -07:00
committed by GitHub
49 changed files with 820 additions and 225 deletions

View File

@ -9,13 +9,41 @@ on:
- "**/*.py" - "**/*.py"
jobs: jobs:
very_old_python:
if: github.event.pull_request.draft == false
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-13, windows-2019]
python-version: ["3.6"]
steps:
- uses: actions/checkout@v3
- name: "Set up timezone to America/Los_Angeles"
uses: szenius/set-timezone@v1.2
with:
timezoneLinux: "America/Los_Angeles"
timezoneMacos: "America/Los_Angeles"
timezoneWindows: "Pacific Standard Time"
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test with unittest
run: |
python -m unittest discover tests
old_python: old_python:
if: github.event.pull_request.draft == false if: github.event.pull_request.draft == false
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [macos-13, ubuntu-20.04, windows-2019] os: [macos-13, ubuntu-22.04, windows-2019]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] python-version: ["3.7", "3.8", "3.9", "3.10"]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3

View File

@ -1,5 +1,17 @@
jc changelog jc changelog
20250503 v1.25.5
- Add `amixer` command parser
- Enhance `iptables` command parser to add default policy statistics fields
- Fix `bluetoothctl` parser failing to parse controllers with power state prop
- Fix `lsblk` command parser to support multiple mountpoints. Also, added
byte conversions for size fields.
- Fix `nmcli` command parser to support `team.config` JSON field
- Fix `time` command parser for output that does not contain centiseconds
- Fix `x509-cert` parser to handle IDNA2008 encoded email addresses with a warning
- Fix typing for upcoming python v3.14
- Fix timezone setting for tests to support minimal chrooted builds
20241125 v1.25.4 20241125 v1.25.4
- Add `ipconfig` command parser (`ipconfig` for Windows) - Add `ipconfig` command parser (`ipconfig` for Windows)
- Add `pacman` command parser - Add `pacman` command parser

View File

@ -159,6 +159,7 @@ option.
| `--acpi` | `acpi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi) | | `--acpi` | `acpi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi) |
| `--airport` | `airport -I` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport) | | `--airport` | `airport -I` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport) |
| `--airport-s` | `airport -s` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s) | | `--airport-s` | `airport -s` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s) |
| `--amixer` | `amixer` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/amixer) |
| `--apt-cache-show` | `apt-cache show` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/apt_cache_show) | | `--apt-cache-show` | `apt-cache show` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/apt_cache_show) |
| `--apt-get-sqq` | `apt-get -sqq` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/apt_get_sqq) | | `--apt-get-sqq` | `apt-get -sqq` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/apt_get_sqq) |
| `--arp` | `arp` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/arp) | | `--arp` | `arp` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/arp) |
@ -1378,4 +1379,4 @@ cat istio.yaml | jc -p --yaml
] ]
``` ```
© 2019-2024 Kelly Brazil © 2019-2025 Kelly Brazil

View File

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

View File

@ -9,10 +9,11 @@ _jc() {
jc_help_options jc_help_options_describe \ jc_help_options jc_help_options_describe \
jc_special_options jc_special_options_describe jc_special_options jc_special_options_describe
jc_commands=(acpi airport apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool) jc_commands=(acpi airport amixer apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool)
jc_commands_describe=( jc_commands_describe=(
'acpi:run "acpi" command with magic syntax.' 'acpi:run "acpi" command with magic syntax.'
'airport:run "airport" command with magic syntax.' 'airport:run "airport" command with magic syntax.'
'amixer:run "amixer" command with magic syntax.'
'apt-cache:run "apt-cache" command with magic syntax.' 'apt-cache:run "apt-cache" command with magic syntax.'
'apt-get:run "apt-get" command with magic syntax.' 'apt-get:run "apt-get" command with magic syntax.'
'arp:run "arp" command with magic syntax.' 'arp:run "arp" command with magic syntax.'
@ -124,11 +125,12 @@ _jc() {
'zipinfo:run "zipinfo" command with magic syntax.' 'zipinfo:run "zipinfo" command with magic syntax.'
'zpool:run "zpool" command with magic syntax.' 'zpool:run "zpool" command with magic syntax.'
) )
jc_parsers=(--acpi --airport --airport-s --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status) jc_parsers=(--acpi --airport --airport-s --amixer --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_parsers_describe=( jc_parsers_describe=(
'--acpi:`acpi` command parser' '--acpi:`acpi` command parser'
'--airport:`airport -I` command parser' '--airport:`airport -I` command parser'
'--airport-s:`airport -s` command parser' '--airport-s:`airport -s` command parser'
'--amixer:`amixer` command parser'
'--apt-cache-show:`apt-cache show` command parser' '--apt-cache-show:`apt-cache show` command parser'
'--apt-get-sqq:`apt-get -sqq` command parser' '--apt-get-sqq:`apt-get -sqq` command parser'
'--arp:`arp` command parser' '--arp:`arp` command parser'

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

@ -0,0 +1,117 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.amixer"></a>
# jc.parsers.amixer
jc - JSON Convert `amixer sget` command output parser
Usage (cli):
$ amixer sget <control_name> | jc --amixer
$ amixer sget Master | jc --amixer
$ amixer sget Capture | jc --amixer
$ amixer sget Speakers | jc --amixer
Usage (module):
import jc
result = jc.parse('amixer', <amixer_sget_command_output>)
Schema:
{
"control_name": string,
"capabilities": [
string
],
"playback_channels": [
string
],
"limits": {
"playback_min": integer,
"playback_max": integer
},
"mono": {
"playback_value": integer,
"percentage": integer,
"db": float,
"status": boolean
}
}
Examples:
$ amixer sget Master | jc --amixer -p
{
"control_name": "Capture",
"capabilities": [
"cvolume",
"cswitch"
],
"playback_channels": [],
"limits": {
"playback_min": 0,
"playback_max": 63
},
"front_left": {
"playback_value": 63,
"percentage": 100,
"db": 30.0,
"status": true
},
"front_right": {
"playback_value": 63,
"percentage": 100,
"db": 30.0,
"status": true
}
}
$ amixer sget Master | jc --amixer -p -r
{
"control_name": "Master",
"capabilities": [
"pvolume",
"pvolume-joined",
"pswitch",
"pswitch-joined"
],
"playback_channels": [
"Mono"
],
"limits": {
"playback_min": "0",
"playback_max": "87"
},
"mono": {
"playback_value": "87",
"percentage": "100%",
"db": "0.00db",
"status": "on"
}
}
<a id="jc.parsers.amixer.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
Source: [`jc/parsers/amixer.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/amixer.py)
Version 1.0 by Eden Refael (edenraf@hotmail.com)

View File

@ -136,4 +136,4 @@ Compatibility: linux
Source: [`jc/parsers/bluetoothctl.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/bluetoothctl.py) Source: [`jc/parsers/bluetoothctl.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/bluetoothctl.py)
Version 1.3 by Jake Ob (iakopap at gmail.com) Version 1.4 by Jake Ob (iakopap at gmail.com)

View File

@ -25,6 +25,9 @@ Schema:
[ [
{ {
"chain": string, "chain": string,
"default_policy": string,
"default_packets": integer,
"default_bytes": integer,
"rules": [ "rules": [
{ {
"num" integer, "num" integer,
@ -49,6 +52,9 @@ Examples:
[ [
{ {
"chain": "PREROUTING", "chain": "PREROUTING",
"default_policy": "DROP",
"default_packets": 0,
"default_bytes": 0,
"rules": [ "rules": [
{ {
"num": 1, "num": 1,
@ -108,6 +114,9 @@ Examples:
[ [
{ {
"chain": "PREROUTING", "chain": "PREROUTING",
"default_policy": "DROP",
"default_packets": "0",
"default_bytes": "0",
"rules": [ "rules": [
{ {
"num": "1", "num": "1",
@ -188,4 +197,4 @@ Compatibility: linux
Source: [`jc/parsers/iptables.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/iptables.py) Source: [`jc/parsers/iptables.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/iptables.py)
Version 1.11 by Kelly Brazil (kellyjonbrazil@gmail.com) Version 1.12 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -22,46 +22,53 @@ Schema:
[ [
{ {
"name": string, "name": string,
"maj_min": string, "maj_min": string,
"rm": boolean, "rm": boolean,
"size": string, "size": string,
"ro": boolean, "size_bytes": integer
"type": string, "ro": boolean,
"mountpoint": string, "type": string,
"kname": string, "mountpoint": string,
"fstype": string, "mountpoints": [
"label": string, string
"uuid": string, ],
"partlabel": string, "kname": string,
"partuuid": string, "fstype": string,
"ra": integer, "label": string,
"model": string, "uuid": string,
"serial": string, "partlabel": string,
"state": string, "partuuid": string,
"owner": string, "ra": integer,
"group": string, "model": string,
"mode": string, "serial": string,
"alignment": integer, "state": string,
"min_io": integer, "owner": string,
"opt_io": integer, "group": string,
"phy_sec": integer, "mode": string,
"log_sec": integer, "alignment": integer,
"rota": boolean, "min_io": integer,
"sched": string, "opt_io": integer,
"rq_size": integer, "phy_sec": integer,
"disc_aln": integer, "log_sec": integer,
"disc_gran": string, "rota": boolean,
"disc_max": string, "sched": string,
"disc_zero": boolean, "rq_size": integer,
"wsame": string, "disc_aln": integer,
"wwn": string, "disc_gran": string,
"rand": boolean, "disc_gran_bytes": integer,
"pkname": string, "disc_max": string,
"hctl": string, "disc_max_bytes": integer,
"tran": string, "disc_zero": boolean,
"rev": string, "wsame": string,
"vendor": string "wsame_bytes": integer,
"wwn": string,
"rand": boolean,
"pkname": string,
"hctl": string,
"tran": string,
"rev": string,
"vendor": string
} }
] ]
@ -74,6 +81,7 @@ Examples:
"maj_min": "8:0", "maj_min": "8:0",
"rm": false, "rm": false,
"size": "20G", "size": "20G",
"size_bytes": 20000000000,
"ro": false, "ro": false,
"type": "disk", "type": "disk",
"mountpoint": null "mountpoint": null
@ -83,6 +91,7 @@ Examples:
"maj_min": "8:1", "maj_min": "8:1",
"rm": false, "rm": false,
"size": "1G", "size": "1G",
"size_bytes": 1000000000
"ro": false, "ro": false,
"type": "part", "type": "part",
"mountpoint": "/boot" "mountpoint": "/boot"
@ -100,6 +109,7 @@ Examples:
"maj_min": "8:0", "maj_min": "8:0",
"rm": false, "rm": false,
"size": "20G", "size": "20G",
"size_bytes": 20000000000,
"ro": false, "ro": false,
"type": "disk", "type": "disk",
"mountpoint": null, "mountpoint": null,
@ -126,9 +136,12 @@ Examples:
"rq_size": 128, "rq_size": 128,
"disc_aln": 0, "disc_aln": 0,
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": false, "disc_zero": false,
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": true, "rand": true,
"pkname": null, "pkname": null,
@ -142,6 +155,7 @@ Examples:
"maj_min": "8:1", "maj_min": "8:1",
"rm": false, "rm": false,
"size": "1G", "size": "1G",
"size_bytes": 1000000000
"ro": false, "ro": false,
"type": "part", "type": "part",
"mountpoint": "/boot", "mountpoint": "/boot",
@ -168,9 +182,12 @@ Examples:
"rq_size": 128, "rq_size": 128,
"disc_aln": 0, "disc_aln": 0,
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": false, "disc_zero": false,
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": true, "rand": true,
"pkname": "sda", "pkname": "sda",
@ -192,6 +209,7 @@ Examples:
"maj_min": "8:0", "maj_min": "8:0",
"rm": "0", "rm": "0",
"size": "20G", "size": "20G",
"size_bytes": 20000000000,
"ro": "0", "ro": "0",
"type": "disk", "type": "disk",
"mountpoint": null, "mountpoint": null,
@ -218,9 +236,12 @@ Examples:
"rq_size": "128", "rq_size": "128",
"disc_aln": "0", "disc_aln": "0",
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": "0", "disc_zero": "0",
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": "1", "rand": "1",
"pkname": null, "pkname": null,
@ -234,6 +255,7 @@ Examples:
"maj_min": "8:1", "maj_min": "8:1",
"rm": "0", "rm": "0",
"size": "1G", "size": "1G",
"size_bytes": 1000000000
"ro": "0", "ro": "0",
"type": "part", "type": "part",
"mountpoint": "/boot", "mountpoint": "/boot",
@ -260,9 +282,12 @@ Examples:
"rq_size": "128", "rq_size": "128",
"disc_aln": "0", "disc_aln": "0",
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": "0", "disc_zero": "0",
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": "1", "rand": "1",
"pkname": "sda", "pkname": "sda",
@ -299,4 +324,4 @@ Compatibility: linux
Source: [`jc/parsers/lsblk.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/lsblk.py) Source: [`jc/parsers/lsblk.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/lsblk.py)
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com) Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -100,4 +100,4 @@ Compatibility: linux, darwin, freebsd, aix
Source: [`jc/parsers/mount.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/mount.py) Source: [`jc/parsers/mount.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/mount.py)
Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com) Version 1.11 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -41,6 +41,7 @@ These are documented below.
[ [
{ {
"<key>": string/integer/float, # [0] "<key>": string/integer/float, # [0]
"team_config": object,
"dhcp4_option_x": { "dhcp4_option_x": {
"name": string, "name": string,
"value": string/integer/float, "value": string/integer/float,
@ -170,4 +171,4 @@ Compatibility: linux
Source: [`jc/parsers/nmcli.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/nmcli.py) Source: [`jc/parsers/nmcli.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/nmcli.py)
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com) Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -157,4 +157,4 @@ Compatibility: linux, darwin, cygwin, aix, freebsd
Source: [`jc/parsers/time.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/time.py) Source: [`jc/parsers/time.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/time.py)
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -435,4 +435,4 @@ Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Source: [`jc/parsers/x509_cert.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/x509_cert.py) Source: [`jc/parsers/x509_cert.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/x509_cert.py)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -52,7 +52,7 @@ class info():
author: str = 'Kelly Brazil' author: str = 'Kelly Brazil'
author_email: str = 'kellyjonbrazil@gmail.com' author_email: str = 'kellyjonbrazil@gmail.com'
website: str = 'https://github.com/kellyjonbrazil/jc' website: str = 'https://github.com/kellyjonbrazil/jc'
copyright: str = '© 2019-2024 Kelly Brazil' copyright: str = '© 2019-2025 Kelly Brazil'
license: str = 'MIT License' license: str = 'MIT License'

View File

@ -10,7 +10,7 @@ from jc import appdirs
from jc import utils from jc import utils
__version__ = '1.25.4' __version__ = '1.25.5'
parsers: List[str] = [ parsers: List[str] = [
'acpi', 'acpi',

View File

@ -10,7 +10,7 @@ Usage (cli):
Usage (module): Usage (module):
import jc import jc
result = jc.parse('amixer', <amixer sget command output>) result = jc.parse('amixer', <amixer_sget_command_output>)
Schema: Schema:
@ -20,7 +20,7 @@ Schema:
string string
], ],
"playback_channels": [ "playback_channels": [
string string
], ],
"limits": { "limits": {
"playback_min": integer, "playback_min": integer,
@ -85,13 +85,12 @@ Examples:
"status": "on" "status": "on"
} }
} }
""" """
from typing import List, Dict from typing import Dict
import jc.utils import jc.utils
from jc.utils import convert_to_int from jc.utils import convert_to_int
from jc.exceptions import ParseError
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
@ -107,7 +106,7 @@ class info():
__version__ = info.version __version__ = info.version
def _process(proc_data: dict) -> dict: def _process(proc_data: Dict) -> Dict:
""" """
Processes raw structured data to match the schema requirements. Processes raw structured data to match the schema requirements.
@ -117,6 +116,9 @@ def _process(proc_data: dict) -> dict:
Returns: Returns:
(dict) processed structured data adhering to the schema (dict) processed structured data adhering to the schema
""" """
if not proc_data:
return {}
# Initialize the processed dictionary # Initialize the processed dictionary
processed = { processed = {
"control_name": proc_data.get("control_name", ""), "control_name": proc_data.get("control_name", ""),
@ -147,20 +149,17 @@ def parse(
data: str, data: str,
raw: bool = False, raw: bool = False,
quiet: bool = False quiet: bool = False
) -> List[Dict]: ) -> Dict:
""" """
Main text parsing function, The amixer is alsa mixer tool and output, Will work with Linux OS only. Main text parsing function
Parameters: Parameters:
data: (string) text data to parse data: (string) text data to parse
raw: (boolean) unprocessed output if True raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
Returns: Returns:
List of Dictionaries. Raw or processed structured data. Dictionary. Raw or processed structured data.
push test
""" """
""" """
The Algorithm for parsing the `amixer sget` command, Input Explained/Rules/Pseudo Algorithm: The Algorithm for parsing the `amixer sget` command, Input Explained/Rules/Pseudo Algorithm:
@ -172,7 +171,6 @@ def parse(
3b. Playback channels - List of channels 3b. Playback channels - List of channels
4. Limits - We'll always have the minimum limit and the maximum limit. 4. Limits - We'll always have the minimum limit and the maximum limit.
Input Example: Input Example:
1."":~$ amixer sget Capture 1."":~$ amixer sget Capture
Simple mixer control 'Capture',0 Simple mixer control 'Capture',0
@ -182,9 +180,6 @@ def parse(
Front Left: Capture 63 [100%] [30.00db] [on] Front Left: Capture 63 [100%] [30.00db] [on]
Front Right: Capture 63 [100%] [30.00db] [on] Front Right: Capture 63 [100%] [30.00db] [on]
2."":~$ amixer sget Master 2."":~$ amixer sget Master
Simple mixer control 'Master',0 Simple mixer control 'Master',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined Capabilities: pvolume pvolume-joined pswitch pswitch-joined
@ -192,10 +187,6 @@ def parse(
Limits: Playback 0 - 87 Limits: Playback 0 - 87
Mono: Playback 87 [100%] [0.00db] [on] Mono: Playback 87 [100%] [0.00db] [on]
3."":~$ amixer sget Speaker 3."":~$ amixer sget Speaker
Simple mixer control 'Speaker',0 Simple mixer control 'Speaker',0
Capabilities: pvolume pswitch Capabilities: pvolume pswitch
@ -205,9 +196,6 @@ def parse(
Front Left: Playback 87 [100%] [0.00db] [on] Front Left: Playback 87 [100%] [0.00db] [on]
Front Right: Playback 87 [100%] [0.00db] [on] Front Right: Playback 87 [100%] [0.00db] [on]
4."":~$ amixer sget Headphone 4."":~$ amixer sget Headphone
Simple mixer control 'Headphone',0 Simple mixer control 'Headphone',0
Capabilities: pvolume pswitch Capabilities: pvolume pswitch
@ -224,54 +212,62 @@ def parse(
jc.utils.input_type_check(data) jc.utils.input_type_check(data)
# starts the parsing from here # starts the parsing from here
mapping = {} mapping: Dict = {}
# split lines and than work on each line
lines = data.splitlines()
first_line = lines[0].strip()
# Extract the control name from the first line if jc.utils.has_data(data):
if first_line.startswith("Simple mixer control"): # split lines and than work on each line
control_name = first_line.split("'")[1] lines = data.splitlines()
else: first_line = lines[0].strip()
raise ValueError("Invalid amixer output format: missing control name.")
# map the control name
mapping["control_name"] = control_name
# Process subsequent lines for capabilities, channels, limits, and channel-specific mapping. # Extract the control name from the first line
# gets the lines from the next line - because we already took care the first line. if first_line.startswith("Simple mixer control"):
for line in lines[1:]: control_name = first_line.split("'")[1]
# strip the line (maybe there are white spaces in the begin&end) else:
line = line.strip() raise ParseError("Invalid amixer output format: missing control name.")
# map the control name
mapping["control_name"] = control_name
if line.startswith("Capabilities:"): # Process subsequent lines for capabilities, channels, limits, and channel-specific mapping.
mapping["capabilities"] = line.split(":")[1].strip().split() # gets the lines from the next line - because we already took care the first line.
elif line.startswith("Playback channels:"): for line in lines[1:]:
mapping["playback_channels"] = line.split(":")[1].strip().split(" - ") # strip the line (maybe there are white spaces in the begin&end)
elif line.startswith("Limits:"): line = line.strip()
limits = line.split(":")[1].strip().split(" - ")
mapping["limits"] = {
"playback_min": limits[0].split()[1],
"playback_max": limits[1]
}
elif line.startswith("Mono:") or line.startswith("Front Left:") or line.startswith("Front Right:"):
# Identify the channel name and parse its information
channel_name = line.split(":")[0].strip().lower().replace(" ", "_")
channel_info = line.split(":")[1].strip()
# Example: "Playback 255 [100%] [0.00db] [on]"
channel_data = channel_info.split(" ")
if channel_data[0] == "":
continue
playback_value = channel_data[1]
percentage = channel_data[2].strip("[]") # Extract percentage e.g., "100%"
db_value = channel_data[3].strip("[]") # Extract db value e.g., "0.00db"
status = channel_data[4].strip("[]") # Extract status e.g., "on" or "off"
# Store channel mapping in the dictionary if line.startswith("Capabilities:"):
mapping[channel_name] = { mapping["capabilities"] = line.split(":")[1].strip().split()
"playback_value": playback_value, elif line.startswith("Playback channels:"):
"percentage": percentage, mapping["playback_channels"] = line.split(":")[1].strip().split(" - ")
"db": db_value.lower(), elif line.startswith("Limits:"):
"status": status limits = line.split(":")[1].strip().split(" - ")
} mapping["limits"] = {
"playback_min": limits[0].split()[1],
"playback_max": limits[1]
}
elif line.startswith("Mono:") or line.startswith("Front Left:") or line.startswith("Front Right:"):
# Identify the channel name and parse its information
channel_name = line.split(":")[0].strip().lower().replace(" ", "_")
channel_info = line.split(":")[1].strip()
# Example: "Playback 255 [100%] [0.00db] [on]"
channel_data = channel_info.split(" ")
if channel_data[0] == "":
continue
if "dB" in channel_data[3]:
db_value = channel_data[3].strip("[]")
status = channel_data[4].strip("[]")
else:
db_value = "0.0db"
status = channel_data[3].strip("[]")
playback_value = channel_data[1]
percentage = channel_data[2].strip("[]") # Extract percentage e.g., "100%"
# Store channel mapping in the dictionary
mapping[channel_name] = {
"playback_value": playback_value,
"percentage": percentage,
"db": db_value.lower(),
"status": status
}
return mapping if raw else _process(mapping) return mapping if raw else _process(mapping)

View File

@ -255,7 +255,7 @@ class EmailAddress(IA5String):
# fix to allow incorrectly encoded email addresses to succeed with warning # fix to allow incorrectly encoded email addresses to succeed with warning
try: try:
self._unicode = mailbox.decode('cp1252') + '@' + hostname.decode('idna') self._unicode = mailbox.decode('cp1252') + '@' + hostname.decode('idna')
except UnicodeDecodeError: except (UnicodeDecodeError, UnicodeError):
ascii_mailbox = mailbox.decode('ascii', errors='backslashreplace') ascii_mailbox = mailbox.decode('ascii', errors='backslashreplace')
ascii_hostname = hostname.decode('ascii', errors='backslashreplace') ascii_hostname = hostname.decode('ascii', errors='backslashreplace')
from jc.utils import warning_message from jc.utils import warning_message

View File

@ -112,7 +112,7 @@ import jc.utils
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.3' version = '1.4'
description = '`bluetoothctl` command parser' description = '`bluetoothctl` command parser'
author = 'Jake Ob' author = 'Jake Ob'
author_email = 'iakopap at gmail.com' author_email = 'iakopap at gmail.com'
@ -139,6 +139,7 @@ try:
"alias": str, "alias": str,
"class": str, "class": str,
"powered": str, "powered": str,
"power_state": str,
"discoverable": str, "discoverable": str,
"discoverable_timeout": str, "discoverable_timeout": str,
"pairable": str, "pairable": str,
@ -185,6 +186,7 @@ _controller_line_pattern = (
+ r"|\s*Alias:\s*(?P<alias>.+)" + r"|\s*Alias:\s*(?P<alias>.+)"
+ r"|\s*Class:\s*(?P<class>.+)" + r"|\s*Class:\s*(?P<class>.+)"
+ r"|\s*Powered:\s*(?P<powered>.+)" + r"|\s*Powered:\s*(?P<powered>.+)"
+ r"|\s*PowerState:\s*(?P<power_state>.+)"
+ r"|\s*Discoverable:\s*(?P<discoverable>.+)" + r"|\s*Discoverable:\s*(?P<discoverable>.+)"
+ r"|\s*DiscoverableTimeout:\s*(?P<discoverable_timeout>.+)" + r"|\s*DiscoverableTimeout:\s*(?P<discoverable_timeout>.+)"
+ r"|\s*Pairable:\s*(?P<pairable>.+)" + r"|\s*Pairable:\s*(?P<pairable>.+)"
@ -219,6 +221,7 @@ def _parse_controller(next_lines: List[str]) -> Optional[Controller]:
"alias": '', "alias": '',
"class": '', "class": '',
"powered": '', "powered": '',
"power_state": '',
"discoverable": '', "discoverable": '',
"discoverable_timeout": '', "discoverable_timeout": '',
"pairable": '', "pairable": '',
@ -261,6 +264,8 @@ def _parse_controller(next_lines: List[str]) -> Optional[Controller]:
controller["class"] = matches["class"] controller["class"] = matches["class"]
elif matches["powered"]: elif matches["powered"]:
controller["powered"] = matches["powered"] controller["powered"] = matches["powered"]
elif matches["power_state"]:
controller["power_state"] = matches["power_state"]
elif matches["discoverable"]: elif matches["discoverable"]:
controller["discoverable"] = matches["discoverable"] controller["discoverable"] = matches["discoverable"]
elif matches["discoverable_timeout"]: elif matches["discoverable_timeout"]:

View File

@ -20,6 +20,9 @@ Schema:
[ [
{ {
"chain": string, "chain": string,
"default_policy": string,
"default_packets": integer,
"default_bytes": integer,
"rules": [ "rules": [
{ {
"num" integer, "num" integer,
@ -44,6 +47,9 @@ Examples:
[ [
{ {
"chain": "PREROUTING", "chain": "PREROUTING",
"default_policy": "DROP",
"default_packets": 0,
"default_bytes": 0,
"rules": [ "rules": [
{ {
"num": 1, "num": 1,
@ -103,6 +109,9 @@ Examples:
[ [
{ {
"chain": "PREROUTING", "chain": "PREROUTING",
"default_policy": "DROP",
"default_packets": "0",
"default_bytes": "0",
"rules": [ "rules": [
{ {
"num": "1", "num": "1",
@ -158,12 +167,13 @@ Examples:
... ...
] ]
""" """
import re
import jc.utils import jc.utils
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.11' version = '1.12'
description = '`iptables` command parser' description = '`iptables` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
@ -174,6 +184,17 @@ class info():
__version__ = info.version __version__ = info.version
chain_pkt_byt_pattern = re.compile(
r'''
\s\(policy\s
(?P<policy_name>.+)
\s
(?P<packets>.+)
\spackets,\s
(?P<bytes>.+)
\sbytes\)
''', re.VERBOSE
)
def _process(proc_data): def _process(proc_data):
""" """
@ -188,6 +209,13 @@ def _process(proc_data):
List of Dictionaries. Structured data to conform to the schema. List of Dictionaries. Structured data to conform to the schema.
""" """
for entry in proc_data: for entry in proc_data:
if 'default_packets' in entry:
entry['default_packets'] = jc.utils.convert_to_int(entry['default_packets'])
if 'default_bytes' in entry:
entry['default_bytes'] = jc.utils.convert_size_to_int(entry['default_bytes'])
for rule in entry['rules']: for rule in entry['rules']:
int_list = ['num', 'pkts'] int_list = ['num', 'pkts']
for key in rule: for key in rule:
@ -243,6 +271,14 @@ def parse(data, raw=False, quiet=False):
parsed_line = line.split() parsed_line = line.split()
chain['chain'] = parsed_line[1] chain['chain'] = parsed_line[1]
stats_match = re.search(chain_pkt_byt_pattern, line)
if stats_match:
stats = stats_match.groupdict()
chain['default_policy'] = stats['policy_name']
chain['default_packets'] = stats['packets']
chain['default_bytes'] = stats['bytes']
chain['rules'] = [] chain['rules'] = []
continue continue

View File

@ -17,46 +17,53 @@ Schema:
[ [
{ {
"name": string, "name": string,
"maj_min": string, "maj_min": string,
"rm": boolean, "rm": boolean,
"size": string, "size": string,
"ro": boolean, "size_bytes": integer
"type": string, "ro": boolean,
"mountpoint": string, "type": string,
"kname": string, "mountpoint": string,
"fstype": string, "mountpoints": [
"label": string, string
"uuid": string, ],
"partlabel": string, "kname": string,
"partuuid": string, "fstype": string,
"ra": integer, "label": string,
"model": string, "uuid": string,
"serial": string, "partlabel": string,
"state": string, "partuuid": string,
"owner": string, "ra": integer,
"group": string, "model": string,
"mode": string, "serial": string,
"alignment": integer, "state": string,
"min_io": integer, "owner": string,
"opt_io": integer, "group": string,
"phy_sec": integer, "mode": string,
"log_sec": integer, "alignment": integer,
"rota": boolean, "min_io": integer,
"sched": string, "opt_io": integer,
"rq_size": integer, "phy_sec": integer,
"disc_aln": integer, "log_sec": integer,
"disc_gran": string, "rota": boolean,
"disc_max": string, "sched": string,
"disc_zero": boolean, "rq_size": integer,
"wsame": string, "disc_aln": integer,
"wwn": string, "disc_gran": string,
"rand": boolean, "disc_gran_bytes": integer,
"pkname": string, "disc_max": string,
"hctl": string, "disc_max_bytes": integer,
"tran": string, "disc_zero": boolean,
"rev": string, "wsame": string,
"vendor": string "wsame_bytes": integer,
"wwn": string,
"rand": boolean,
"pkname": string,
"hctl": string,
"tran": string,
"rev": string,
"vendor": string
} }
] ]
@ -69,6 +76,7 @@ Examples:
"maj_min": "8:0", "maj_min": "8:0",
"rm": false, "rm": false,
"size": "20G", "size": "20G",
"size_bytes": 20000000000,
"ro": false, "ro": false,
"type": "disk", "type": "disk",
"mountpoint": null "mountpoint": null
@ -78,6 +86,7 @@ Examples:
"maj_min": "8:1", "maj_min": "8:1",
"rm": false, "rm": false,
"size": "1G", "size": "1G",
"size_bytes": 1000000000
"ro": false, "ro": false,
"type": "part", "type": "part",
"mountpoint": "/boot" "mountpoint": "/boot"
@ -95,6 +104,7 @@ Examples:
"maj_min": "8:0", "maj_min": "8:0",
"rm": false, "rm": false,
"size": "20G", "size": "20G",
"size_bytes": 20000000000,
"ro": false, "ro": false,
"type": "disk", "type": "disk",
"mountpoint": null, "mountpoint": null,
@ -121,9 +131,12 @@ Examples:
"rq_size": 128, "rq_size": 128,
"disc_aln": 0, "disc_aln": 0,
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": false, "disc_zero": false,
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": true, "rand": true,
"pkname": null, "pkname": null,
@ -137,6 +150,7 @@ Examples:
"maj_min": "8:1", "maj_min": "8:1",
"rm": false, "rm": false,
"size": "1G", "size": "1G",
"size_bytes": 1000000000
"ro": false, "ro": false,
"type": "part", "type": "part",
"mountpoint": "/boot", "mountpoint": "/boot",
@ -163,9 +177,12 @@ Examples:
"rq_size": 128, "rq_size": 128,
"disc_aln": 0, "disc_aln": 0,
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": false, "disc_zero": false,
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": true, "rand": true,
"pkname": "sda", "pkname": "sda",
@ -187,6 +204,7 @@ Examples:
"maj_min": "8:0", "maj_min": "8:0",
"rm": "0", "rm": "0",
"size": "20G", "size": "20G",
"size_bytes": 20000000000,
"ro": "0", "ro": "0",
"type": "disk", "type": "disk",
"mountpoint": null, "mountpoint": null,
@ -213,9 +231,12 @@ Examples:
"rq_size": "128", "rq_size": "128",
"disc_aln": "0", "disc_aln": "0",
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": "0", "disc_zero": "0",
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": "1", "rand": "1",
"pkname": null, "pkname": null,
@ -229,6 +250,7 @@ Examples:
"maj_min": "8:1", "maj_min": "8:1",
"rm": "0", "rm": "0",
"size": "1G", "size": "1G",
"size_bytes": 1000000000
"ro": "0", "ro": "0",
"type": "part", "type": "part",
"mountpoint": "/boot", "mountpoint": "/boot",
@ -255,9 +277,12 @@ Examples:
"rq_size": "128", "rq_size": "128",
"disc_aln": "0", "disc_aln": "0",
"disc_gran": "0B", "disc_gran": "0B",
"disc_gran_bytes": 0,
"disc_max": "0B", "disc_max": "0B",
"disc_max_bytes": 0,
"disc_zero": "0", "disc_zero": "0",
"wsame": "32M", "wsame": "32M",
"wsame_bytes": 32000000,
"wwn": null, "wwn": null,
"rand": "1", "rand": "1",
"pkname": "sda", "pkname": "sda",
@ -275,7 +300,7 @@ import jc.parsers.universal
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.9' version = '1.10'
description = '`lsblk` command parser' description = '`lsblk` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
@ -304,14 +329,19 @@ def _process(proc_data):
int_list = {'ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec', int_list = {'ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec',
'rq_size', 'disc_aln'} 'rq_size', 'disc_aln'}
size_list = {'size', 'disc_gran', 'disc_max', 'wsame'}
for entry in proc_data: for entry in proc_data:
for key in entry: for key in entry.copy():
if key in bool_list: if key in bool_list:
entry[key] = jc.utils.convert_to_bool(entry[key]) entry[key] = jc.utils.convert_to_bool(entry[key])
if key in int_list: if key in int_list:
entry[key] = jc.utils.convert_to_int(entry[key]) entry[key] = jc.utils.convert_to_int(entry[key])
if key in size_list:
entry[key + '_bytes'] = jc.utils.convert_size_to_int(entry[key], posix_mode=True)
return proc_data return proc_data
@ -335,6 +365,7 @@ def parse(data, raw=False, quiet=False):
# Clear any blank lines # Clear any blank lines
cleandata = list(filter(None, data.splitlines())) cleandata = list(filter(None, data.splitlines()))
raw_output = [] raw_output = []
new_list = []
if jc.utils.has_data(data): if jc.utils.has_data(data):
@ -346,11 +377,23 @@ def parse(data, raw=False, quiet=False):
raw_output = jc.parsers.universal.sparse_table_parse(cleandata) raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
# clean up non-ascii characters, if any # find multiple mount points and add to a single entry
for entry in raw_output: for entry in raw_output:
entry['name'] = entry['name'].encode('ascii', errors='ignore').decode() if entry['name']:
if 'mountpoints' in entry:
if entry['mountpoints']:
entry['mountpoints'] = [entry['mountpoints']]
else:
entry['mountpoints'] = []
new_list.append(entry)
elif 'mountpoints' in entry and entry['mountpoints']:
new_list[-1]['mountpoints'].append(entry['mountpoints'])
if raw: # clean up tree characters, if any
return raw_output for entry in new_list:
else: tree_chars = ['`-', '|-', '├─', '└─']
return _process(raw_output) for chars in tree_chars:
if entry['name'][0:2] == chars:
entry['name'] = entry['name'][2:]
return new_list if raw else _process(new_list)

View File

@ -71,13 +71,12 @@ Example:
] ]
""" """
import re import re
import jc.utils import jc.utils
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.10' version = '1.11'
description = '`mount` command parser' description = '`mount` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
@ -111,19 +110,24 @@ def _osx_parse(data):
for entry in data: for entry in data:
output_line = {} output_line = {}
filesystem = entry.split(' on ') pattern = re.compile(
filesystem = filesystem[0] r'''
output_line['filesystem'] = filesystem (?P<filesystem>.*)
\son\s
(?P<mount_point>.*?)
\s
\((?P<options>.*?)\)\s*
''', re.VERBOSE
)
mount_point = entry.split(' on ') mymatch = pattern.match(entry)
mount_point = mount_point[1].split(' (') groups = mymatch.groupdict()
mount_point = mount_point[0]
output_line['mount_point'] = mount_point
options = entry.split('(', maxsplit=1) if groups:
options = options[1].rstrip(')') output_line['filesystem'] = groups['filesystem']
options = options.split(', ') output_line['mount_point'] = groups['mount_point']
output_line['options'] = options options = groups['options'].split(', ')
output_line['options'] = options
output.append(output_line) output.append(output_line)
@ -218,7 +222,7 @@ def parse(data, raw=False, quiet=False):
# check for OSX and AIX output # check for OSX and AIX output
if ' type ' not in cleandata[0]: if ' type ' not in cleandata[0]:
if 'node' in cleandata[0]: if ' node ' in cleandata[0]:
raw_output = _aix_parse(cleandata) raw_output = _aix_parse(cleandata)
else: else:
raw_output = _osx_parse(cleandata) raw_output = _osx_parse(cleandata)

View File

@ -36,6 +36,7 @@ These are documented below.
[ [
{ {
"<key>": string/integer/float, # [0] "<key>": string/integer/float, # [0]
"team_config": object,
"dhcp4_option_x": { "dhcp4_option_x": {
"name": string, "name": string,
"value": string/integer/float, "value": string/integer/float,
@ -141,6 +142,7 @@ Examples:
] ]
""" """
import re import re
import json
from typing import List, Dict, Optional from typing import List, Dict, Optional
import jc.utils import jc.utils
from jc.parsers.universal import sparse_table_parse from jc.parsers.universal import sparse_table_parse
@ -149,7 +151,7 @@ from jc.exceptions import ParseError
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.0' version = '1.1'
description = '`nmcli` command parser' description = '`nmcli` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
@ -313,8 +315,30 @@ def _device_show_parse(data: str) -> List[Dict]:
def _connection_show_x_parse(data: str) -> List[Dict]: def _connection_show_x_parse(data: str) -> List[Dict]:
raw_output: List = [] raw_output: List = []
item: Dict = {} item: Dict = {}
in_team_config: bool = False
team_config_value: List = []
for line in filter(None, data.splitlines()): for line in filter(None, data.splitlines()):
# fix for team.config, which is multi-line JSON
if line.startswith('team.config:'):
in_team_config = True
_, value = line.split(':', maxsplit=1)
team_config_value.append(value.strip())
item['team_config'] = {}
continue
if not line.startswith('team.') and in_team_config:
team_config_value.append(line.strip())
continue
in_team_config = False
if team_config_value:
# team.config value should always be JSON
item['team_config'] = json.loads(''.join(team_config_value))
team_config_value = []
key, value = line.split(':', maxsplit=1) key, value = line.split(':', maxsplit=1)
key_n = _normalize_key(key) key_n = _normalize_key(key)

View File

@ -4,7 +4,6 @@ Edid module
import struct import struct
from collections import namedtuple from collections import namedtuple
from typing import ByteString
__all__ = ["Edid"] __all__ = ["Edid"]
@ -108,10 +107,10 @@ class Edid:
), ),
) )
def __init__(self, edid: ByteString): def __init__(self, edid: bytes):
self._parse_edid(edid) self._parse_edid(edid)
def _parse_edid(self, edid: ByteString): def _parse_edid(self, edid: bytes):
"""Convert edid byte string to edid object""" """Convert edid byte string to edid object"""
if struct.calcsize(self._STRUCT_FORMAT) != 128: if struct.calcsize(self._STRUCT_FORMAT) != 128:
raise ValueError("Wrong edid size.") raise ValueError("Wrong edid size.")

View File

@ -3,7 +3,7 @@ EDID helper
""" """
from subprocess import CalledProcessError, check_output from subprocess import CalledProcessError, check_output
from typing import ByteString, List from typing import List
__all__ = ["EdidHelper"] __all__ = ["EdidHelper"]
@ -12,14 +12,14 @@ class EdidHelper:
"""Class for working with EDID data""" """Class for working with EDID data"""
@staticmethod @staticmethod
def hex2bytes(hex_data: str) -> ByteString: def hex2bytes(hex_data: str) -> bytes:
"""Convert hex EDID string to bytes """Convert hex EDID string to bytes
Args: Args:
hex_data (str): hex edid string hex_data (str): hex edid string
Returns: Returns:
ByteString: edid byte string bytes: edid byte string
""" """
# delete edid 1.3 additional block # delete edid 1.3 additional block
if len(hex_data) > 256: if len(hex_data) > 256:
@ -32,14 +32,14 @@ class EdidHelper:
return bytes(numbers) return bytes(numbers)
@classmethod @classmethod
def get_edids(cls) -> List[ByteString]: def get_edids(cls) -> List[bytes]:
"""Get edids from xrandr """Get edids from xrandr
Raises: Raises:
`RuntimeError`: if error with retrieving xrandr util data `RuntimeError`: if error with retrieving xrandr util data
Returns: Returns:
List[ByteString]: list with edids List[bytes]: list with edids
""" """
try: try:
output = check_output(["xrandr", "--verbose"]) output = check_output(["xrandr", "--verbose"])

View File

@ -132,7 +132,7 @@ import jc.utils
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.4' version = '1.5'
description = '`/usr/bin/time` command parser' description = '`/usr/bin/time` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
@ -171,13 +171,18 @@ def _process(proc_data):
proc_data['command_being_timed'] = proc_data['command_being_timed'][1:-1] proc_data['command_being_timed'] = proc_data['command_being_timed'][1:-1]
if 'elapsed_time' in proc_data: if 'elapsed_time' in proc_data:
proc_data['elapsed_time'] = proc_data['elapsed_time'].replace('.', ':') *hours, minutes, ss = proc_data['elapsed_time'].split(':')
*hours, minutes, seconds, centiseconds = proc_data['elapsed_time'].split(':') if '.' in ss:
proc_data['elapsed_time'] = proc_data['elapsed_time'][::-1].replace(':', '.', 1)[::-1] seconds, centiseconds = ss.split('.')
else:
seconds = ss
centiseconds = '0'
if hours: if hours:
proc_data['elapsed_time_hours'] = jc.utils.convert_to_int(hours[0]) proc_data['elapsed_time_hours'] = jc.utils.convert_to_int(hours[0])
else: else:
proc_data['elapsed_time_hours'] = 0 proc_data['elapsed_time_hours'] = 0
proc_data['elapsed_time_minutes'] = jc.utils.convert_to_int(minutes) proc_data['elapsed_time_minutes'] = jc.utils.convert_to_int(minutes)
proc_data['elapsed_time_seconds'] = jc.utils.convert_to_int(seconds) proc_data['elapsed_time_seconds'] = jc.utils.convert_to_int(seconds)
proc_data['elapsed_time_centiseconds'] = jc.utils.convert_to_int(centiseconds) proc_data['elapsed_time_centiseconds'] = jc.utils.convert_to_int(centiseconds)

View File

@ -413,7 +413,7 @@ from jc.parsers.asn1crypto import pem, x509, jc_global
class info(): class info():
"""Provides parser metadata (version, author, etc.)""" """Provides parser metadata (version, author, etc.)"""
version = '1.3' version = '1.4'
description = 'X.509 PEM and DER certificate file parser' description = 'X.509 PEM and DER certificate file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'

View File

@ -1,4 +1,4 @@
.TH jc 1 2024-11-25 1.25.4 "JSON Convert" .TH jc 1 2025-05-10 1.25.5 "JSON Convert"
.SH NAME .SH NAME
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, \fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types,
and strings and strings
@ -52,6 +52,11 @@ Parsers:
\fB--airport-s\fP \fB--airport-s\fP
`airport -s` command parser `airport -s` command parser
.TP
.B
\fB--amixer\fP
`amixer` command parser
.TP .TP
.B .B
\fB--apt-cache-show\fP \fB--apt-cache-show\fP
@ -1632,6 +1637,6 @@ Kelly Brazil (kellyjonbrazil@gmail.com)
https://github.com/kellyjonbrazil/jc https://github.com/kellyjonbrazil/jc
.SH COPYRIGHT .SH COPYRIGHT
Copyright (c) 2019-2024 Kelly Brazil Copyright (c) 2019-2025 Kelly Brazil
License: MIT License License: MIT License

View File

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# system should be in "America/Los_Angeles" timezone for all tests to pass # system should be in "America/Los_Angeles" (PST8PDT) timezone for all tests
# ensure no local plugin parsers are installed for all tests to pass # to pass ensure no local plugin parsers are installed for all tests to pass
TZ=America/Los_Angeles python3 -m unittest -v TZ=PST8PDT python3 -m unittest -v

View File

@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
setuptools.setup( setuptools.setup(
name='jc', name='jc',
version='1.25.4', version='1.25.5',
author='Kelly Brazil', author='Kelly Brazil',
author_email='kellyjonbrazil@gmail.com', author_email='kellyjonbrazil@gmail.com',
description='Converts the output of popular command-line tools and file-types to JSON.', description='Converts the output of popular command-line tools and file-types to JSON.',

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
[{"name": "sda", "maj_min": "8:0", "rm": false, "size": "20G", "ro": false, "type": "disk", "mountpoint": null, "kname": "sda", "fstype": null, "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 4096, "model": "VMware Virtual S", "serial": null, "state": "running", "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": true, "pkname": null, "hctl": "0:0:0:0", "tran": "spi", "rev": "1.0", "vendor": "VMware,"}, {"name": "sda1", "maj_min": "8:1", "rm": false, "size": "1G", "ro": false, "type": "part", "mountpoint": "/boot", "kname": "sda1", "fstype": "xfs", "label": null, "uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": true, "pkname": "sda", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "sda2", "maj_min": "8:2", "rm": false, "size": "19G", "ro": false, "type": "part", "mountpoint": null, "kname": "sda2", "fstype": "LVM2_member", "label": null, "uuid": "3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": true, "pkname": "sda", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "centos-root", "maj_min": "253:0", "rm": false, "size": "17G", "ro": false, "type": "lvm", "mountpoint": "/", "kname": "dm-0", "fstype": "xfs", "label": null, "uuid": "07d718ef-950c-4e5b-98e0-42a1147b77d9", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": "running", "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": null, "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": false, "pkname": "sda2", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "centos-swap", "maj_min": "253:1", "rm": false, "size": "2G", "ro": false, "type": "lvm", "mountpoint": "[SWAP]", "kname": "dm-1", "fstype": "swap", "label": null, "uuid": "615eb89d-bcbf-46ad-80e3-c483ef5c931f", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": "running", "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": null, "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": false, "pkname": "sda2", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "sr0", "maj_min": "11:0", "rm": true, "size": "1024M", "ro": false, "type": "rom", "mountpoint": null, "kname": "sr0", "fstype": null, "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": "VMware IDE CDR10", "serial": "10000000000000000001", "state": "running", "owner": "root", "group": "cdrom", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": null, "hctl": "2:0:0:0", "tran": "ata", "rev": "1.00", "vendor": "NECVMWar"}] [{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"kname":"sda","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":4096,"model":"VMware Virtual S","serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":null,"hctl":"0:0:0:0","tran":"spi","rev":"1.0","vendor":"VMware,","size_bytes":21474836480,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","kname":"sda1","fstype":"xfs","label":null,"uuid":"05d927bb-5875-49e3-ada1-7f46cb31c932","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1073741824,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"kname":"sda2","fstype":"LVM2_member","label":null,"uuid":"3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":20401094656,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","kname":"dm-0","fstype":"xfs","label":null,"uuid":"07d718ef-950c-4e5b-98e0-42a1147b77d9","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":18253611008,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","kname":"dm-1","fstype":"swap","label":null,"uuid":"615eb89d-bcbf-46ad-80e3-c483ef5c931f","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":2147483648,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"kname":"sr0","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":"VMware IDE CDR10","serial":"10000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"2:0:0:0","tran":"ata","rev":"1.00","vendor":"NECVMWar","size_bytes":1073741824,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0}]

View File

@ -1 +1 @@
[{"name": "sda", "maj_min": "8:0", "rm": false, "size": "20G", "ro": false, "type": "disk", "mountpoint": null}, {"name": "sda1", "maj_min": "8:1", "rm": false, "size": "1G", "ro": false, "type": "part", "mountpoint": "/boot"}, {"name": "sda2", "maj_min": "8:2", "rm": false, "size": "19G", "ro": false, "type": "part", "mountpoint": null}, {"name": "centos-root", "maj_min": "253:0", "rm": false, "size": "17G", "ro": false, "type": "lvm", "mountpoint": "/"}, {"name": "centos-swap", "maj_min": "253:1", "rm": false, "size": "2G", "ro": false, "type": "lvm", "mountpoint": "[SWAP]"}, {"name": "sr0", "maj_min": "11:0", "rm": true, "size": "1024M", "ro": false, "type": "rom", "mountpoint": null}] [{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":21474836480},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","size_bytes":1073741824},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"size_bytes":20401094656},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","size_bytes":18253611008},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","size_bytes":2147483648},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"size_bytes":1073741824}]

View File

@ -0,0 +1,20 @@
Controller CC:52:AF:17:6A:E4 (public)
Manufacturer: 0x000f (15)
Version: 0x05 (5)
Name: starbase
Alias: starbase
Class: 0x006c010c (7078156)
Powered: yes
PowerState: on
Discoverable: no
DiscoverableTimeout: 0x000000b4 (180)
Pairable: no
UUID: Handsfree (0000111e-0000-1000-8000-00805f9b34fb)
UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb)
UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
UUID: Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb)
Modalias: usb:v1D6Bp0246d054F
Discovering: no

View File

@ -0,0 +1 @@
[{"filesystem":"/dev/disk3s1s1","mount_point":"/","options":["apfs","sealed","local","read-only","journaled"]},{"filesystem":"devfs","mount_point":"/dev","options":["devfs","local","nobrowse"]},{"filesystem":"/dev/disk3s6","mount_point":"/System/Volumes/VM","options":["apfs","local","noexec","journaled","noatime","nobrowse"]},{"filesystem":"/dev/disk3s2","mount_point":"/System/Volumes/Preboot","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk3s4","mount_point":"/System/Volumes/Update","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk2s2","mount_point":"/System/Volumes/xarts","options":["apfs","local","noexec","journaled","noatime","nobrowse"]},{"filesystem":"/dev/disk2s1","mount_point":"/System/Volumes/iSCPreboot","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk2s3","mount_point":"/System/Volumes/Hardware","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk3s5","mount_point":"/System/Volumes/Data","options":["apfs","local","journaled","nobrowse","protect","root data"]},{"filesystem":"map auto_home","mount_point":"/System/Volumes/Data/home","options":["autofs","automounted","nobrowse"]},{"filesystem":"MN - mydomain.com (ftp.mydomain.com):/","mount_point":"/Users/muescha/Library/Application Support/Mountain Duck/Volumes.noindex/MN - mydomain.com.localized","options":["nfs","asynchronous","nodev","nosuid","noowners","noatime","mounted by muescha"]},{"filesystem":"/dev/disk5s1","mount_point":"/Library/Developer/CoreSimulator/Volumes/iOS_21F79","options":["apfs","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]},{"filesystem":"/dev/disk7s1","mount_point":"/Library/Developer/CoreSimulator/Cryptex/Images/bundle/SimRuntimeBundle-A3CF7B3B-543B-4D71-BA03-12F939EA0B4D","options":["apfs","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]},{"filesystem":"/dev/disk9s1","mount_point":"/Library/Developer/CoreSimulator/Volumes/iOS_22C150","options":["apfs","sealed","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]}]

View File

@ -0,0 +1,14 @@
/dev/disk3s1s1 on / (apfs, sealed, local, read-only, journaled)
devfs on /dev (devfs, local, nobrowse)
/dev/disk3s6 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk3s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse)
/dev/disk3s4 on /System/Volumes/Update (apfs, local, journaled, nobrowse)
/dev/disk2s2 on /System/Volumes/xarts (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk2s1 on /System/Volumes/iSCPreboot (apfs, local, journaled, nobrowse)
/dev/disk2s3 on /System/Volumes/Hardware (apfs, local, journaled, nobrowse)
/dev/disk3s5 on /System/Volumes/Data (apfs, local, journaled, nobrowse, protect, root data)
map auto_home on /System/Volumes/Data/home (autofs, automounted, nobrowse)
MN - mydomain.com (ftp.mydomain.com):/ on /Users/muescha/Library/Application Support/Mountain Duck/Volumes.noindex/MN - mydomain.com.localized (nfs, asynchronous, nodev, nosuid, noowners, noatime, mounted by muescha)
/dev/disk5s1 on /Library/Developer/CoreSimulator/Volumes/iOS_21F79 (apfs, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse)
/dev/disk7s1 on /Library/Developer/CoreSimulator/Cryptex/Images/bundle/SimRuntimeBundle-A3CF7B3B-543B-4D71-BA03-12F939EA0B4D (apfs, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse)
/dev/disk9s1 on /Library/Developer/CoreSimulator/Volumes/iOS_22C150 (apfs, sealed, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse)

Binary file not shown.

View File

@ -0,0 +1 @@
[{"tbs_certificate":{"version":"v3","serial_number":"37:12:43:a3:c9:eb:75:b7:61:6f:39:5f:0f:4d:a9:d4:6a:67:61:c2","signature":{"algorithm":"sha256_ecdsa","parameters":null},"issuer":{"common_name":"idna issues Inc."},"validity":{"not_before":1744299375,"not_after":2059659375,"not_before_iso":"2025-04-10T15:36:15+00:00","not_after_iso":"2035-04-08T15:36:15+00:00"},"subject":{"common_name":"idna issues Inc."},"subject_public_key_info":{"algorithm":{"algorithm":"ec","parameters":"secp256r1"},"public_key":"04:c4:e7:a0:b8:d0:5a:d3:77:86:e9:b2:b4:0d:4c:4f:52:25:0b:53:5b:21:5e:f1:50:1e:4f:6c:f4:8f:44:03:50:c2:ee:0e:61:2b:56:09:25:5c:4c:17:2a:78:cd:d2:ff:f5:8f:0e:68:eb:c9:4b:8a:18:0d:62:8d:9b:46:5f:71"},"issuer_unique_id":null,"subject_unique_id":null,"extensions":[{"extn_id":"subject_alt_name","critical":false,"extn_value":["sesam@xn--strae-oqa.de"]}],"serial_number_str":"314401798066465365584221074488388179068992315842"},"signature_algorithm":{"algorithm":"sha256_ecdsa","parameters":null},"signature_value":"30:46:02:21:00:9c:3b:38:eb:d6:52:e4:49:4b:4c:0a:19:04:56:45:66:31:4f:fd:c0:8d:ec:6c:c7:61:61:81:40:08:55:64:c2:02:21:00:f9:a1:38:ea:5a:f0:c1:2e:7c:c1:92:bd:f8:20:77:dd:50:63:5b:6d:7e:8a:35:28:97:bf:30:b0:db:d0:85:f1"}]

View File

@ -1 +1 @@
[{"chain": "INPUT", "rules": [{"pkts": 66, "bytes": 6034, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 1137, "bytes": 318000, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "15.15.15.51", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}]}, {"chain": "FORWARD", "rules": []}, {"chain": "OUTPUT", "rules": [{"pkts": 66, "bytes": 6034, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 889, "bytes": 158000, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}]}] [{"chain":"INPUT","default_policy":"ACCEPT","default_packets":0,"default_bytes":0,"rules":[{"pkts":66,"bytes":6034,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":1137,"bytes":318000,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"lo","out":"*","source":"15.15.15.51","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"}]},{"chain":"FORWARD","default_policy":"ACCEPT","default_packets":0,"default_bytes":0,"rules":[]},{"chain":"OUTPUT","default_policy":"ACCEPT","default_packets":4,"default_bytes":277,"rules":[{"pkts":66,"bytes":6034,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":889,"bytes":158000,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"}]}]

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
[{"name": "fd0", "maj_min": "2:0", "rm": true, "size": "1.4M", "ro": false, "type": "disk", "mountpoint": null}, {"name": "loop0", "maj_min": "7:0", "rm": false, "size": "54.5M", "ro": true, "type": "loop", "mountpoint": "/snap/core18/1223"}, {"name": "loop1", "maj_min": "7:1", "rm": false, "size": "11M", "ro": true, "type": "loop", "mountpoint": "/snap/slcli/383"}, {"name": "loop2", "maj_min": "7:2", "rm": false, "size": "88.7M", "ro": true, "type": "loop", "mountpoint": "/snap/core/7396"}, {"name": "loop3", "maj_min": "7:3", "rm": false, "size": "66.5M", "ro": true, "type": "loop", "mountpoint": "/snap/google-cloud-sdk/103"}, {"name": "loop4", "maj_min": "7:4", "rm": false, "size": "66.5M", "ro": true, "type": "loop", "mountpoint": "/snap/google-cloud-sdk/104"}, {"name": "loop5", "maj_min": "7:5", "rm": false, "size": "54.4M", "ro": true, "type": "loop", "mountpoint": "/snap/core18/1074"}, {"name": "loop7", "maj_min": "7:7", "rm": false, "size": "8.6M", "ro": true, "type": "loop", "mountpoint": "/snap/doctl/187"}, {"name": "loop8", "maj_min": "7:8", "rm": false, "size": "3.1M", "ro": true, "type": "loop", "mountpoint": "/snap/stress-ng/847"}, {"name": "loop9", "maj_min": "7:9", "rm": false, "size": "8.6M", "ro": true, "type": "loop", "mountpoint": "/snap/doctl/215"}, {"name": "loop10", "maj_min": "7:10", "rm": false, "size": "89.1M", "ro": true, "type": "loop", "mountpoint": "/snap/core/7917"}, {"name": "loop11", "maj_min": "7:11", "rm": false, "size": "3.2M", "ro": true, "type": "loop", "mountpoint": "/snap/stress-ng/924"}, {"name": "sda", "maj_min": "8:0", "rm": false, "size": "20G", "ro": false, "type": "disk", "mountpoint": null}, {"name": "sda1", "maj_min": "8:1", "rm": false, "size": "1M", "ro": false, "type": "part", "mountpoint": null}, {"name": "sda2", "maj_min": "8:2", "rm": false, "size": "20G", "ro": false, "type": "part", "mountpoint": "/"}, {"name": "sr0", "maj_min": "11:0", "rm": true, "size": "64.8M", "ro": false, "type": "rom", "mountpoint": null}, {"name": "sr1", "maj_min": "11:1", "rm": true, "size": "848M", "ro": false, "type": "rom", "mountpoint": null}] [{"name":"fd0","maj_min":"2:0","rm":true,"size":"1.4M","ro":false,"type":"disk","mountpoint":null,"size_bytes":1468006},{"name":"loop0","maj_min":"7:0","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1223","size_bytes":57147392},{"name":"loop1","maj_min":"7:1","rm":false,"size":"11M","ro":true,"type":"loop","mountpoint":"/snap/slcli/383","size_bytes":11534336},{"name":"loop2","maj_min":"7:2","rm":false,"size":"88.7M","ro":true,"type":"loop","mountpoint":"/snap/core/7396","size_bytes":93008691},{"name":"loop3","maj_min":"7:3","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/103","size_bytes":69730304},{"name":"loop4","maj_min":"7:4","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/104","size_bytes":69730304},{"name":"loop5","maj_min":"7:5","rm":false,"size":"54.4M","ro":true,"type":"loop","mountpoint":"/snap/core18/1074","size_bytes":57042534},{"name":"loop7","maj_min":"7:7","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/187","size_bytes":9017753},{"name":"loop8","maj_min":"7:8","rm":false,"size":"3.1M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/847","size_bytes":3250585},{"name":"loop9","maj_min":"7:9","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/215","size_bytes":9017753},{"name":"loop10","maj_min":"7:10","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/7917","size_bytes":93428121},{"name":"loop11","maj_min":"7:11","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/924","size_bytes":3355443},{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":21474836480},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1M","ro":false,"type":"part","mountpoint":null,"size_bytes":1048576},{"name":"sda2","maj_min":"8:2","rm":false,"size":"20G","ro":false,"type":"part","mountpoint":"/","size_bytes":21474836480},{"name":"sr0","maj_min":"11:0","rm":true,"size":"64.8M","ro":false,"type":"rom","mountpoint":null,"size_bytes":67947724},{"name":"sr1","maj_min":"11:1","rm":true,"size":"848M","ro":false,"type":"rom","mountpoint":null,"size_bytes":889192448}]

Binary file not shown.

View File

@ -22,27 +22,49 @@ class AmixerTests(unittest.TestCase):
self.test_files_json = [f'{file}.json' for file in self.TEST_FILES_NAME] self.test_files_json = [f'{file}.json' for file in self.TEST_FILES_NAME]
self.test_files_processed_json = [f'{file}-processed.json' for file in self.TEST_FILES_NAME] self.test_files_processed_json = [f'{file}-processed.json' for file in self.TEST_FILES_NAME]
def test_amixer_sget_nodata(self):
"""
Test 'amixer' with no data
"""
self.assertEqual(jc.parsers.amixer.parse('', quiet=True), {})
def test_amixer_sget(self): def test_amixer_sget(self):
for file_out, file_json, file_processed_json in zip(self.test_files_out, self.test_files_json, for file_out, file_json, file_processed_json in zip(self.test_files_out, self.test_files_json,
self.test_files_processed_json): self.test_files_processed_json):
with open(file_out, 'r') as f: with open(file_out, 'r') as f:
amixer_sget_raw_output: str = f.read() amixer_sget_raw_output = f.read()
with open(file_json, 'r') as f: with open(file_json, 'r') as f:
expected_amixer_sget_json_output: str = f.read() expected_amixer_sget_json_output = f.read()
expected_amixer_sget_json_map: dict = json.loads(expected_amixer_sget_json_output) expected_amixer_sget_json_map = json.loads(expected_amixer_sget_json_output)
with open(file_processed_json, 'r') as f: with open(file_processed_json, 'r') as f:
expected_amixer_sget_processed_json_output: str = f.read() expected_amixer_sget_processed_json_output = f.read()
expected_amixer_sget_processed_json_map: dict = json.loads(expected_amixer_sget_processed_json_output) expected_amixer_sget_processed_json_map = json.loads(expected_amixer_sget_processed_json_output)
# Tests for raw=True # Tests for raw=True
amixer_sget_json_map: dict = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=True, amixer_sget_json_map = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=True,
quiet=True) quiet=True)
self.assertEqual(amixer_sget_json_map, expected_amixer_sget_json_map) self.assertEqual(amixer_sget_json_map, expected_amixer_sget_json_map)
# Tests for raw=False process # Tests for raw=False process
amixer_sget_json_processed_map: dict = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=False, amixer_sget_json_processed_map = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=False,
quiet=True) quiet=True)
self.assertEqual(amixer_sget_json_processed_map, expected_amixer_sget_processed_json_map) self.assertEqual(amixer_sget_json_processed_map, expected_amixer_sget_processed_json_map)
def test_amixer_missing_db(self):
data = '''Simple mixer control 'Master',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 65536
Mono:
Front Left: Playback 55039 [84%] [on]
Front Right: Playback 54383 [83%] [on]
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch cswitch-joined
Capture channels: Front Left - Front Right
Limits: Capture 0 - 65536
Front Left: Capture 24672 [38%] [on]
Front Right: Capture 24672 [38%] [on]'''
expected = {"control_name":"Master","capabilities":["cvolume","cswitch","cswitch-joined"],"playback_channels":["Front Left","Front Right"],"limits":{"playback_min":0,"playback_max":65536},"front_left":{"playback_value":24672,"percentage":38,"db":0.0,"status":True},"front_right":{"playback_value":24672,"percentage":38,"db":0.0,"status":True}}
self.assertEqual(expected, jc.parsers.amixer.parse(data, quiet=True))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -104,7 +104,48 @@ class BluetoothctlTests(unittest.TestCase):
if actual: if actual:
for k, v in expected.items(): for k, v in expected.items():
self.assertEqual(v, actual[0][k], f"Controller regex failed on {k}") self.assertEqual(v, actual[0][k], f"Controller regex failed on {k}")
def test_bluetoothctl_controller_2(self):
"""
Test 'bluetoothctl' with controller 2
"""
with open("tests/fixtures/generic/bluetoothctl_controller_2.out", "r") as f:
output = f.read()
actual = parse(output, quiet=True)
self.assertIsNotNone(actual)
self.assertIsNotNone(actual[0])
expected = {
"address": "CC:52:AF:17:6A:E4",
"is_public": True,
"name": "starbase",
"alias": "starbase",
"class": "0x006c010c (7078156)",
"powered": "yes",
"power_state": "on",
"discoverable": "no",
"discoverable_timeout": "0x000000b4 (180)",
"pairable": "no",
"uuids": [
"Handsfree (0000111e-0000-1000-8000-00805f9b34fb)",
"Audio Source (0000110a-0000-1000-8000-00805f9b34fb)",
"Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)",
"PnP Information (00001200-0000-1000-8000-00805f9b34fb)",
"A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)",
"A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)",
"Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb)"
],
"modalias": "usb:v1D6Bp0246d054F",
"discovering": "no"
}
if actual:
for k, v in expected.items():
self.assertEqual(v, actual[0][k], f"Controller regex failed on {k}")
def test_bluetoothctl_controller_with_manufacturer(self): def test_bluetoothctl_controller_with_manufacturer(self):
""" """
Test 'bluetoothctl' with controller having manufacturer attr Test 'bluetoothctl' with controller having manufacturer attr

View File

@ -200,7 +200,7 @@ class MyTests(unittest.TestCase):
128627559125 172804718595966 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0 128627559125 172804718595966 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
26599 1082920 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID 26599 1082920 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
1761 79571 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited''' 1761 79571 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited'''
expected = [{"chain":"INPUT","rules":[{"pkts":11291792498,"bytes":217331852907122,"target":"ACCEPT","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":555958,"bytes":33533576,"target":"ACCEPT","prot":"all","opt":None,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":128628404869,"bytes":172804745659762,"target":"INPUT_direct","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":128627559128,"bytes":172804718596050,"target":"INPUT_ZONES_SOURCE","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":128627559125,"bytes":172804718595966,"target":"INPUT_ZONES","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":26599,"bytes":1082920,"target":"DROP","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":1761,"bytes":79571,"target":"REJECT","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"reject-with icmp-host-prohibited"}]}] expected = [{'chain': 'INPUT', 'default_policy': 'ACCEPT', 'default_packets': 0, 'default_bytes': 0, 'rules': [{'pkts': 11291792498, 'bytes': 217331852907122, 'target': 'ACCEPT', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0', 'options': 'ctstate RELATED,ESTABLISHED'}, {'pkts': 555958, 'bytes': 33533576, 'target': 'ACCEPT', 'prot': 'all', 'opt': None, 'in': 'lo', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 128628404869, 'bytes': 172804745659762, 'target': 'INPUT_direct', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 128627559128, 'bytes': 172804718596050, 'target': 'INPUT_ZONES_SOURCE', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 128627559125, 'bytes': 172804718595966, 'target': 'INPUT_ZONES', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 26599, 'bytes': 1082920, 'target': 'DROP', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0', 'options': 'ctstate INVALID'}, {'pkts': 1761, 'bytes': 79571, 'target': 'REJECT', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0', 'options': 'reject-with icmp-host-prohibited'}]}]
self.assertEqual(jc.parsers.iptables.parse(data, quiet=True), expected) self.assertEqual(jc.parsers.iptables.parse(data, quiet=True), expected)

View File

@ -65,6 +65,24 @@ class MyTests(unittest.TestCase):
""" """
self.assertEqual(jc.parsers.lsblk.parse(self.ubuntu_18_4_lsblk_allcols, quiet=True), self.ubuntu_18_4_lsblk_allcols_json) self.assertEqual(jc.parsers.lsblk.parse(self.ubuntu_18_4_lsblk_allcols, quiet=True), self.ubuntu_18_4_lsblk_allcols_json)
def test_lsblk_multiple_mountpoints(self):
"""
Test 'lsblk' with multiple mountpoints
"""
data = '''NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 5368709120000 0 disk
|-sda1 8:1 0 1048576 0 part
|-sda2 8:2 0 1073741824 0 part /boot
|-sda3 8:3 0 1073741824 0 part /boot/efi
`-sda4 8:4 0 51536461824 0 part
|-almalinux-root 253:0 0 36075208704 0 lvm /
|-almalinux-docker 253:1 0 1073741824 0 lvm /opt/docker
|-almalinux-home 253:2 0 5368709120 0 lvm /home
`-almalinux-opt 253:3 0 9017753600 0 lvm /var/lib/kafka
/opt
sr0 11:0 1 1073741312 0 rom'''
expected = [{"name":"sda","maj_min":"8:0","rm":False,"size":"5368709120000","ro":False,"type":"disk","mountpoints":[],"size_bytes":5368709120000},{"name":"sda1","maj_min":"8:1","rm":False,"size":"1048576","ro":False,"type":"part","mountpoints":[],"size_bytes":1048576},{"name":"sda2","maj_min":"8:2","rm":False,"size":"1073741824","ro":False,"type":"part","mountpoints":["/boot"],"size_bytes":1073741824},{"name":"sda3","maj_min":"8:3","rm":False,"size":"1073741824","ro":False,"type":"part","mountpoints":["/boot/efi"],"size_bytes":1073741824},{"name":"sda4","maj_min":"8:4","rm":False,"size":"51536461824","ro":False,"type":"part","mountpoints":[],"size_bytes":51536461824},{"name":"almalinux-root","maj_min":"253:0","rm":False,"size":"36075208704","ro":False,"type":"lvm","mountpoints":["/"],"size_bytes":36075208704},{"name":"almalinux-docker","maj_min":"253:1","rm":False,"size":"1073741824","ro":False,"type":"lvm","mountpoints":["/opt/docker"],"size_bytes":1073741824},{"name":"almalinux-home","maj_min":"253:2","rm":False,"size":"5368709120","ro":False,"type":"lvm","mountpoints":["/home"],"size_bytes":5368709120},{"name":"almalinux-opt","maj_min":"253:3","rm":False,"size":"9017753600","ro":False,"type":"lvm","mountpoints":["/var/lib/kafka","/opt"],"size_bytes":9017753600},{"name":"sr0","maj_min":"11:0","rm":True,"size":"1073741312","ro":False,"type":"rom","mountpoints":[],"size_bytes":1073741312}]
self.assertEqual(jc.parsers.lsblk.parse(data, quiet=True), expected)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -30,6 +30,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.out'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.out'), 'r', encoding='utf-8') as f:
generic_mount_spaces_in_filename = f.read() generic_mount_spaces_in_filename = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-parens-in-filesystem.out'), 'r', encoding='utf-8') as f:
generic_mount_parens_in_filesystem = f.read()
# output # output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/mount.json'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/mount.json'), 'r', encoding='utf-8') as f:
@ -53,6 +56,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.json'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.json'), 'r', encoding='utf-8') as f:
generic_mount_spaces_in_filename_json = json.loads(f.read()) generic_mount_spaces_in_filename_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-parens-in-filesystem.json'), 'r', encoding='utf-8') as f:
generic_mount_parens_in_filesystem_json = json.loads(f.read())
def test_mount_nodata(self): def test_mount_nodata(self):
""" """
@ -102,6 +108,12 @@ class MyTests(unittest.TestCase):
""" """
self.assertEqual(jc.parsers.mount.parse(self.generic_mount_spaces_in_filename, quiet=True), self.generic_mount_spaces_in_filename_json) self.assertEqual(jc.parsers.mount.parse(self.generic_mount_spaces_in_filename, quiet=True), self.generic_mount_spaces_in_filename_json)
def test_mount_parens_in_filesystem(self):
"""
Test 'mount' with parenthesis in the filesystem
"""
self.assertEqual(jc.parsers.mount.parse(self.generic_mount_parens_in_filesystem, quiet=True), self.generic_mount_parens_in_filesystem_json)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -185,6 +185,117 @@ class MyTests(unittest.TestCase):
""" """
self.assertEqual(jc.parsers.nmcli.parse(self.fedora32_nmcli_device_show, quiet=True), self.fedora32_nmcli_device_show_json) self.assertEqual(jc.parsers.nmcli.parse(self.fedora32_nmcli_device_show, quiet=True), self.fedora32_nmcli_device_show_json)
def test_nmcli_team_config(self):
"""
Test nmcli with team.config JSON value
"""
data = '''connection.id: Team connection 1
connection.uuid: 258e02c2-d9f9-44bb-8d27-887e11aa1828
connection.stable-id: --
connection.type: team
connection.interface-name: team0
connection.autoconnect: yes
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 0
connection.read-only: no
connection.permissions: --
connection.zone: --
connection.master: --
connection.slave-type: --
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: unknown
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
connection.wait-device-timeout: -1
ipv4.method: auto
ipv4.dns: --
ipv4.dns-search: --
ipv4.dns-options: --
ipv4.dns-priority: 0
ipv4.addresses: --
ipv4.gateway: --
ipv4.routes: --
ipv4.route-metric: -1
ipv4.route-table: 0 (unspec)
ipv4.routing-rules: --
ipv4.ignore-auto-routes: no
ipv4.ignore-auto-dns: no
ipv4.dhcp-client-id: --
ipv4.dhcp-iaid: --
ipv4.dhcp-timeout: 0 (default)
ipv4.dhcp-send-hostname: yes
ipv4.dhcp-hostname: --
ipv4.dhcp-fqdn: --
ipv4.dhcp-hostname-flags: 0x0 (none)
ipv4.never-default: no
ipv4.may-fail: yes
ipv4.required-timeout: -1 (default)
ipv4.dad-timeout: -1 (default)
ipv4.dhcp-vendor-class-identifier: --
ipv4.dhcp-reject-servers: --
ipv6.method: auto
ipv6.dns: --
ipv6.dns-search: --
ipv6.dns-options: --
ipv6.dns-priority: 0
ipv6.addresses: --
ipv6.gateway: --
ipv6.routes: --
ipv6.route-metric: -1
ipv6.route-table: 0 (unspec)
ipv6.routing-rules: --
ipv6.ignore-auto-routes: no
ipv6.ignore-auto-dns: no
ipv6.never-default: no
ipv6.may-fail: yes
ipv6.required-timeout: -1 (default)
ipv6.ip6-privacy: -1 (unknown)
ipv6.addr-gen-mode: stable-privacy
ipv6.ra-timeout: 0 (default)
ipv6.dhcp-duid: --
ipv6.dhcp-iaid: --
ipv6.dhcp-timeout: 0 (default)
ipv6.dhcp-send-hostname: yes
ipv6.dhcp-hostname: --
ipv6.dhcp-hostname-flags: 0x0 (none)
ipv6.token: --
team.config: {
"runner": {
"name": "roundrobin"
},
"link_watch": {
"name": "ethtool"
}
}
team.notify-peers-count: -1 (unset)
team.notify-peers-interval: -1 (unset)
team.mcast-rejoin-count: -1 (unset)
team.mcast-rejoin-interval: -1 (unset)
team.runner: roundrobin
team.runner-hwaddr-policy: --
team.runner-tx-hash: --
team.runner-tx-balancer: --
team.runner-tx-balancer-interval: -1 (unset)
team.runner-active: yes
team.runner-fast-rate: no
team.runner-sys-prio: -1 (unset)
team.runner-min-ports: -1 (unset)
team.runner-agg-select-policy: --
team.link-watchers: name=ethtool
proxy.method: none
proxy.browser-only: no
proxy.pac-url: --
proxy.pac-script: --'''
expected = [{'connection_id': 'Team connection 1', 'connection_uuid': '258e02c2-d9f9-44bb-8d27-887e11aa1828', 'connection_stable_id': None, 'connection_type': 'team', 'connection_interface_name': 'team0', 'connection_autoconnect': 'yes', 'connection_autoconnect_priority': 0, 'connection_autoconnect_retries': -1, 'connection_autoconnect_retries_text': 'default', 'connection_multi_connect': 0, 'connection_multi_connect_text': 'default', 'connection_auth_retries': -1, 'connection_timestamp': 0, 'connection_read_only': 'no', 'connection_permissions': None, 'connection_zone': None, 'connection_master': None, 'connection_slave_type': None, 'connection_autoconnect_slaves': -1, 'connection_autoconnect_slaves_text': 'default', 'connection_secondaries': None, 'connection_gateway_ping_timeout': 0, 'connection_metered': 'unknown', 'connection_lldp': 'default', 'connection_mdns': -1, 'connection_mdns_text': 'default', 'connection_llmnr': -1, 'connection_llmnr_text': 'default', 'connection_dns_over_tls': -1, 'connection_dns_over_tls_text': 'default', 'connection_wait_device_timeout': -1, 'ipv4_method': 'auto', 'ipv4_dns': None, 'ipv4_dns_search': None, 'ipv4_dns_options': None, 'ipv4_dns_priority': 0, 'ipv4_addresses': None, 'ipv4_gateway': None, 'ipv4_routes': None, 'ipv4_route_metric': -1, 'ipv4_route_table': 0, 'ipv4_route_table_text': 'unspec', 'ipv4_routing_rules': None, 'ipv4_ignore_auto_routes': 'no', 'ipv4_ignore_auto_dns': 'no', 'ipv4_dhcp_client_id': None, 'ipv4_dhcp_iaid': None, 'ipv4_dhcp_timeout': 0, 'ipv4_dhcp_timeout_text': 'default', 'ipv4_dhcp_send_hostname': 'yes', 'ipv4_dhcp_hostname': None, 'ipv4_dhcp_fqdn': None, 'ipv4_dhcp_hostname_flags': '0x0', 'ipv4_dhcp_hostname_flags_text': 'none', 'ipv4_never_default': 'no', 'ipv4_may_fail': 'yes', 'ipv4_required_timeout': -1, 'ipv4_required_timeout_text': 'default', 'ipv4_dad_timeout': -1, 'ipv4_dad_timeout_text': 'default', 'ipv4_dhcp_vendor_class_identifier': None, 'ipv4_dhcp_reject_servers': None, 'ipv6_method': 'auto', 'ipv6_dns': None, 'ipv6_dns_search': None, 'ipv6_dns_options': None, 'ipv6_dns_priority': 0, 'ipv6_addresses': None, 'ipv6_gateway': None, 'ipv6_routes': None, 'ipv6_route_metric': -1, 'ipv6_route_table': 0, 'ipv6_route_table_text': 'unspec', 'ipv6_routing_rules': None, 'ipv6_ignore_auto_routes': 'no', 'ipv6_ignore_auto_dns': 'no', 'ipv6_never_default': 'no', 'ipv6_may_fail': 'yes', 'ipv6_required_timeout': -1, 'ipv6_required_timeout_text': 'default', 'ipv6_ip6_privacy': -1, 'ipv6_ip6_privacy_text': 'unknown', 'ipv6_addr_gen_mode': 'stable-privacy', 'ipv6_ra_timeout': 0, 'ipv6_ra_timeout_text': 'default', 'ipv6_dhcp_duid': None, 'ipv6_dhcp_iaid': None, 'ipv6_dhcp_timeout': 0, 'ipv6_dhcp_timeout_text': 'default', 'ipv6_dhcp_send_hostname': 'yes', 'ipv6_dhcp_hostname': None, 'ipv6_dhcp_hostname_flags': '0x0', 'ipv6_dhcp_hostname_flags_text': 'none', 'ipv6_token': None, 'team_config': {'runner': {'name': 'roundrobin'}, 'link_watch': {'name': 'ethtool'}}, 'team_notify_peers_count': -1, 'team_notify_peers_count_text': 'unset', 'team_notify_peers_interval': -1, 'team_notify_peers_interval_text': 'unset', 'team_mcast_rejoin_count': -1, 'team_mcast_rejoin_count_text': 'unset', 'team_mcast_rejoin_interval': -1, 'team_mcast_rejoin_interval_text': 'unset', 'team_runner': 'roundrobin', 'team_runner_hwaddr_policy': None, 'team_runner_tx_hash': None, 'team_runner_tx_balancer': None, 'team_runner_tx_balancer_interval': -1, 'team_runner_tx_balancer_interval_text': 'unset', 'team_runner_active': 'yes', 'team_runner_fast_rate': 'no', 'team_runner_sys_prio': -1, 'team_runner_sys_prio_text': 'unset', 'team_runner_min_ports': -1, 'team_runner_min_ports_text': 'unset', 'team_runner_agg_select_policy': None, 'team_link_watchers': 'name=ethtool', 'proxy_method': 'none', 'proxy_browser_only': 'no', 'proxy_pac_url': None, 'proxy_pac_script': None}]
self.assertEqual(jc.parsers.nmcli.parse(data, quiet=True), expected)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -113,6 +113,37 @@ class MyTests(unittest.TestCase):
""" """
self.assertEqual(jc.parsers.time.parse(self.osx_10_14_6_time_lp, quiet=True), self.osx_10_14_6_time_lp_json) self.assertEqual(jc.parsers.time.parse(self.osx_10_14_6_time_lp, quiet=True), self.osx_10_14_6_time_lp_json)
def test_time_no_centiseconds(self):
"""
Test 'time' output with no centiseconds data
"""
data = ''' Command being timed: "echo"
User time (seconds): 5156.20
System time (seconds): 0.05
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:25:56
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 21760
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 4975
Voluntary context switches: 1
Involuntary context switches: 8159
Swaps: 0
File system inputs: 0
File system outputs: 6272
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0'''
expected = {"command_being_timed":"echo","user_time":5156.2,"system_time":0.05,"cpu_percent":99,"elapsed_time":"1:25:56","average_shared_text_size":0,"average_unshared_data_size":0,"average_stack_size":0,"average_total_size":0,"maximum_resident_set_size":21760,"average_resident_set_size":0,"major_pagefaults":0,"minor_pagefaults":4975,"voluntary_context_switches":1,"involuntary_context_switches":8159,"swaps":0,"block_input_operations":0,"block_output_operations":6272,"messages_sent":0,"messages_received":0,"signals_delivered":0,"page_size":4096,"exit_status":0,"elapsed_time_hours":1,"elapsed_time_minutes":25,"elapsed_time_seconds":56,"elapsed_time_centiseconds":0,"elapsed_time_total_seconds":5156.0}
self.assertEqual(jc.parsers.time.parse(data, quiet=True), expected)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -33,6 +33,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.pem'), 'rb') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.pem'), 'rb') as f:
x509_cert_negative_serial = f.read() x509_cert_negative_serial = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-bad-email2.der'), 'rb') as f:
x509_cert_bad_email2 = f.read()
# output # output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-ca-cert.json'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-ca-cert.json'), 'r', encoding='utf-8') as f:
x509_ca_cert_json = json.loads(f.read()) x509_ca_cert_json = json.loads(f.read())
@ -54,10 +57,13 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-superfluous-bits.json'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-superfluous-bits.json'), 'r', encoding='utf-8') as f:
x509_cert_superfluous_bits_json = json.loads(f.read()) x509_cert_superfluous_bits_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.json'), 'r', encoding='utf-8') as f: with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.json'), 'r', encoding='utf-8') as f:
x509_cert_negative_serial_json = json.loads(f.read()) x509_cert_negative_serial_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-bad-email2.json'), 'r', encoding='utf-8') as f:
x509_cert_bad_email2_json = json.loads(f.read())
def test_x509_cert_nodata(self): def test_x509_cert_nodata(self):
""" """
@ -113,6 +119,12 @@ class MyTests(unittest.TestCase):
""" """
self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_negative_serial, quiet=True), self.x509_cert_negative_serial_json) self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_negative_serial, quiet=True), self.x509_cert_negative_serial_json)
def test_x509_cert_bad_email2(self):
"""
Test 'cat x509-cert-bad-email2.der' (DER file with a non-compliant email address - IDNA2008 encoded)
"""
self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_bad_email2, quiet=True), self.x509_cert_bad_email2_json)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()