jpcli 0.1.3__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
jpcli/main.py CHANGED
@@ -1,45 +1,75 @@
1
1
 
2
2
  import argparse
3
3
  import subprocess
4
- from .parsers import lsmem_parser, free_parser, other_command_parser
4
+ import sys
5
+ from .parsers import lsmem_parser, free_parser, df_parser, lshw_parser, lscpu_parser, cpuinfo_parser, uname_parser, ifconfig_parser, cmdline_parser, os_release_parser, dmesg_parser, journalctl_parser, mcelog_parser
6
+
5
7
 
6
8
  def run_command(command):
9
+
7
10
  result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
8
11
  if result.returncode != 0:
9
12
  raise RuntimeError(f"Command '{command}' failed with error: {result.stderr.decode()}")
10
13
  return result.stdout.decode()
11
14
 
15
+
12
16
  def parse_command_output(command_output, parser_name):
17
+
13
18
  parsers = {
14
19
  'lsmem': lsmem_parser.parse,
15
20
  'free': free_parser.parse,
16
- # Add other parsers here
21
+ 'df': df_parser.parse,
22
+ 'lshw': lshw_parser.parse,
23
+ 'lscpu': lscpu_parser.parse,
24
+ 'cpuinfo': cpuinfo_parser.parse,
25
+ 'uname': uname_parser.parse,
26
+ 'ifconfig': ifconfig_parser.parse,
27
+ 'cmdline': cmdline_parser.parse,
28
+ 'os-release': os_release_parser.parse,
29
+ 'dmesg': dmesg_parser.parse,
30
+ 'journalctl', journalctl_parser.parse,
31
+ 'mcelog', mcelog_parser.parse,
17
32
  }
18
33
  if parser_name in parsers:
19
34
  return parsers[parser_name](command_output)
20
35
  else:
21
36
  raise ValueError(f"No parser found for {parser_name}")
22
37
 
38
+
23
39
  def main():
24
- parser = argparse.ArgumentParser(description='JP - JSON Parser for Linux commands')
25
- parser.add_argument('command', type=str, help='The Linux command to run')
26
- parser.add_argument('parser_name', type=str, nargs='?', default=None, help='The name of the parser to use')
27
40
 
41
+ parser = argparse.ArgumentParser(description="Parse Linux command outputs into JSON")
42
+ parser.add_argument('parser_name', help='The name of the parser to use')
43
+ parser.add_argument('command', nargs='?', default=None, help='The Linux command to run (optional, reads from stdin if omitted)')
28
44
  args = parser.parse_args()
29
- result = jpcli(args.command, args.parser_name)
45
+
46
+ if not args.command and not args.parser_name:
47
+ print("Error: Parser is required when reading from stdin or command for stdout", file=sys.stderr)
48
+ parser.print_help()
49
+ sys.exit(1)
50
+
51
+ if args.command is None:
52
+ args.command = args.parser_name
53
+
54
+ result = jpcli(args.parser_name, args.command)
30
55
  print(result)
31
56
 
32
- def jpcli(command, parser_name=None):
33
- result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
34
- if result.returncode != 0:
35
- print(f"Error: {result.stderr}", file=sys.stderr)
36
- sys.exit(result.returncode)
37
57
 
38
- command_output = result.stdout
39
- if parser_name is None:
40
- parser_name = command.split()[0] # Use the first word of the command as the parser name
58
+ def jpcli(parser_name, command):
59
+
60
+ if sys.stdin.isatty():
61
+ # Not receiving piped data, execute the command
62
+ result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
63
+ if result.returncode != 0:
64
+ print(f"Error: {result.stderr}", file=sys.stderr)
65
+ sys.exit(result.returncode)
66
+ command_output = result.stdout
67
+ else:
68
+ command_output = sys.stdin.read()
69
+ parser_name = command # Use the command as the parser name
70
+
41
71
  return parse_command_output(command_output, parser_name)
42
72
 
73
+
43
74
  if __name__ == '__main__':
44
75
  main()
45
-
@@ -0,0 +1,12 @@
1
+ def parse(cmdline_output):
2
+ """
3
+ Parse the contents of /proc/cmdline.
4
+ """
5
+ cmdline_dict = {}
6
+ for item in cmdline_output.strip().split():
7
+ if '=' in item:
8
+ key, value = item.split('=', 1)
9
+ cmdline_dict[key] = value
10
+ else:
11
+ cmdline_dict[item] = None
12
+ return cmdline_dict
@@ -0,0 +1,33 @@
1
+ # cpuinfo_parser.py
2
+
3
+ def parse(command_output):
4
+ """
5
+ Parses the output of the 'cat /proc/cpuinfo' command into a list of dictionaries,
6
+ where each dictionary contains information about one processor core.
7
+
8
+ Args:
9
+ command_output (str): The string output from the 'cat /proc/cpuinfo' command.
10
+
11
+ Returns:
12
+ list: A list of dictionaries, each representing a CPU core's information.
13
+ """
14
+ processors = []
15
+ current_processor = {}
16
+ lines = command_output.splitlines()
17
+ for line in lines:
18
+ line = line.strip() # Remove leading and trailing whitespace
19
+ if line:
20
+ key_value_pair = line.split(':', 1) # Split only on the first colon
21
+ if len(key_value_pair) == 2:
22
+ key, value = key_value_pair
23
+ key = key.strip()
24
+ value = value.strip()
25
+ current_processor[key] = value
26
+ else:
27
+ # Handle new processor block (empty line)
28
+ if current_processor:
29
+ processors.append(current_processor)
30
+ current_processor = {}
31
+ if current_processor:
32
+ processors.append(current_processor)
33
+ return processors
@@ -0,0 +1,16 @@
1
+ def parse(command_output):
2
+ lines = command_output.splitlines()
3
+ data = []
4
+ headers = [header.strip() for header in lines[0].split()]
5
+
6
+ for line in lines[1:]:
7
+ if not line.strip():
8
+ continue
9
+ values = line.split()
10
+ if len(values) < len(headers):
11
+ # Handle lines with missing values
12
+ values.extend([''] * (len(headers) - len(values)))
13
+ entry = {headers[i]: values[i] for i in range(len(headers))}
14
+ data.append(entry)
15
+
16
+ return data
@@ -0,0 +1,12 @@
1
+ def parse(dmesg_output):
2
+ """
3
+ Parse the contents of dmesg output.
4
+ """
5
+ try:
6
+ dmesg_lines = dmesg_output.strip().split('\n')
7
+ dmesg_list = []
8
+ for line in dmesg_lines:
9
+ dmesg_list.append(line)
10
+ return dmesg_list
11
+ except Exception as e:
12
+ return {"error": str(e), "message": "Failed to parse dmesg output"}
@@ -1,5 +1,6 @@
1
1
  import json
2
2
 
3
+
3
4
  def parse(command_output):
4
5
  lines = command_output.strip().split('\n')
5
6
  headers = lines[0].split()
@@ -19,4 +20,3 @@ def parse(command_output):
19
20
  memory_data.append(entry)
20
21
 
21
22
  return json.dumps(memory_data, indent=2)
22
-
@@ -0,0 +1,40 @@
1
+ import re
2
+
3
+
4
+ def parse(ifconfig_output):
5
+ """
6
+ Parse the output of the `ifconfig` command.
7
+ """
8
+ interfaces = {}
9
+ current_interface = None
10
+
11
+ for line in ifconfig_output.splitlines():
12
+ if not line.startswith(' '):
13
+ if current_interface:
14
+ interfaces[current_interface['name']] = current_interface
15
+ match = re.match(r'(\S+): flags=.*', line)
16
+ if match:
17
+ current_interface = {
18
+ 'name': match.group(1),
19
+ 'inet': [],
20
+ 'inet6': [],
21
+ 'ether': None
22
+ }
23
+ elif current_interface:
24
+ if 'inet ' in line:
25
+ match = re.search(r'inet (\S+)', line)
26
+ if match:
27
+ current_interface['inet'].append(match.group(1))
28
+ elif 'inet6 ' in line:
29
+ match = re.search(r'inet6 (\S+)', line)
30
+ if match:
31
+ current_interface['inet6'].append(match.group(1))
32
+ elif 'ether ' in line:
33
+ match = re.search(r'ether (\S+)', line)
34
+ if match:
35
+ current_interface['ether'] = match.group(1)
36
+
37
+ if current_interface:
38
+ interfaces[current_interface['name']] = current_interface
39
+
40
+ return interfaces
@@ -0,0 +1,12 @@
1
+ def parse(journalctl_output):
2
+ """
3
+ Parse the contents of journalctl output.
4
+ """
5
+ try:
6
+ journalctl_lines = journalctl_output.strip().split('\n')
7
+ journalctl_list = []
8
+ for line in journalctl_lines:
9
+ journalctl_list.append(line)
10
+ return journalctl_list
11
+ except Exception as e:
12
+ return {"error": str(e), "message": "Failed to parse journalctl output"}
@@ -0,0 +1,33 @@
1
+ def parse(command_output):
2
+ """
3
+ Parses the output of the lscpu command into a dictionary.
4
+
5
+ Args:
6
+ command_output (str): The string output from the lscpu command.
7
+
8
+ Returns:
9
+ dict: A dictionary with CPU properties as keys and their corresponding values.
10
+ """
11
+ cpu_info = {}
12
+ lines = command_output.splitlines()
13
+ for line in lines:
14
+ if line.strip(): # Ensure the line is not empty
15
+ parts = line.split(':')
16
+ if len(parts) == 2:
17
+ key = parts[0].strip()
18
+ value = parts[1].strip()
19
+ cpu_info[key] = value
20
+ return cpu_info
21
+
22
+
23
+ def lscpu_parser(command_output):
24
+ """
25
+ Wrapper function to parse lscpu output.
26
+
27
+ Args:
28
+ command_output (str): The string output from the lscpu command.
29
+
30
+ Returns:
31
+ dict: Parsed CPU information.
32
+ """
33
+ return parse(command_output)
@@ -0,0 +1,38 @@
1
+ def parse(command_output):
2
+ def parse_section(lines, indent_level):
3
+ data = {}
4
+ current_section = {} # Initialize as empty dictionary
5
+ while lines:
6
+ line = lines.pop(0)
7
+ if line.strip() == "":
8
+ continue # Ignore empty lines
9
+ indent = len(line) - len(line.lstrip())
10
+ if indent < indent_level:
11
+ lines.insert(0, line)
12
+ break
13
+ elif line.startswith(' *-'):
14
+ if current_section:
15
+ yield current_section
16
+ current_section = {'description': line.split('-')[-1].strip()} # Initialize here
17
+ elif indent == indent_level and line.startswith(' '):
18
+ parts = line.strip().split(': ', 1)
19
+ if len(parts) == 2:
20
+ current_section[parts[0]] = parts[1] # Direct assignment
21
+ elif len(parts) == 1:
22
+ current_section[parts[0]] = None
23
+ elif indent > indent_level:
24
+ if current_section:
25
+ if 'subsections' not in current_section:
26
+ current_section['subsections'] = []
27
+ current_section['subsections'].extend(parse_section([line] + lines, indent))
28
+ if current_section:
29
+ yield current_section
30
+
31
+ lines = command_output.splitlines()
32
+ result = list(parse_section(lines, 0))
33
+ return result
34
+
35
+
36
+ def lshw_parser(command_output):
37
+ lines = command_output.splitlines()
38
+ return list(parse_section(lines, 0))
@@ -21,4 +21,3 @@ def parse(command_output):
21
21
  data.append(entry)
22
22
 
23
23
  return data
24
-
@@ -0,0 +1,12 @@
1
+ def parse(mcelog_output):
2
+ """
3
+ Parse the contents of mcelog output.
4
+ """
5
+ try:
6
+ mcelog_lines = mcelog_output.strip().split('\n')
7
+ mcelog_list = []
8
+ for line in mcelog_lines:
9
+ mcelog_list.append(line)
10
+ return mcelog_list
11
+ except Exception as e:
12
+ return {"error": str(e), "message": "Failed to parse mcelog output"}
@@ -0,0 +1,11 @@
1
+ # jpcli/parsers/os_release_parser.py
2
+ def parse(os_release_output):
3
+ """
4
+ Parse the contents of /etc/os-release.
5
+ """
6
+ os_release_dict = {}
7
+ for line in os_release_output.strip().split('\n'):
8
+ if '=' in line:
9
+ key, value = line.split('=', 1)
10
+ os_release_dict[key] = value.strip('"')
11
+ return os_release_dict
@@ -0,0 +1,8 @@
1
+ # jpcli/parsers/uname_parser.py
2
+ def parse(uname_output):
3
+ """
4
+ Parse the output of the `uname` command.
5
+ """
6
+ uname_info = uname_output.strip().split()
7
+ keys = ['sysname', 'nodename', 'release', 'version', 'machine', 'processor', 'hardware_platform', 'os']
8
+ return dict(zip(keys, uname_info))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jpcli
3
- Version: 0.1.3
3
+ Version: 0.2.0
4
4
  Summary: A library to convert Linux command output to JSON
5
5
  Home-page: https://github.com/JaimeAdanCuevas/jpcli
6
6
  Author: Jaime Cuevas
@@ -0,0 +1,25 @@
1
+ jpcli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ jpcli/main.py,sha256=TagNzxSxhSV-ttrAomkLIBnHyJRlw5twsKLY0M-3_i0,2610
3
+ jpcli/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ jpcli/parsers/cmdline_parser.py,sha256=HKiI_iGS1Iy6JKJFLUFPsfxyqYo57rPonKfvFfmQTqg,336
5
+ jpcli/parsers/cpuinfo_parser.py,sha256=weYBoGBL8e82kkRAtAJvmWOMx-R3L72gRNKmgAg3DWQ,1177
6
+ jpcli/parsers/df_parser.py,sha256=NC377ld_uUo9MxkGrxYjCAyFq2BdAQL4pgJtz4u3kL8,513
7
+ jpcli/parsers/dmesg_parser.py,sha256=76AkYlcVvo3_5qzuPreTQaelPsExaEct1NDfniiySM0,367
8
+ jpcli/parsers/free_parser.py,sha256=GJuJKCT4cIN4O5D-rHjalx-6FzDT6-lpUurmh9PnUKE,721
9
+ jpcli/parsers/ifconfig_parser.py,sha256=KgtXPGG6QKKFID4YjHwJbL-jbTVoFB8SBjIyop2ICL4,1319
10
+ jpcli/parsers/journalctl_parser.py,sha256=1pGAlrM7oe2vOCnspjdHk_RqDUDxlL2sBpfJJXlWxDU,412
11
+ jpcli/parsers/lscpu_parser.py,sha256=8kAqrFLyVR-vEW6ODlx1fwF1HRNeCTt2CHQ2ZI1bQWg,881
12
+ jpcli/parsers/lshw_parser.py,sha256=QUHE3ya64aaH9Md0VqMK-YQo457W8V8RgClxS41zRx8,1558
13
+ jpcli/parsers/lsmem_parser.py,sha256=vdIyK0xsbrfkqxWOx6jLz-2gsrH5Ii-8mwx-PkL_fXI,744
14
+ jpcli/parsers/mcelog_parser.py,sha256=z62xUwSy_DU-KlPh6d-Xmrz2qMQYVG8JDs7aZE7i7Gk,376
15
+ jpcli/parsers/os_release_parser.py,sha256=5x_tjsG2Jvw1Lx-hVHHbuAMc3d8POPXDQ7Kt9Ux6GG4,353
16
+ jpcli/parsers/uname_parser.py,sha256=dSPRtiSVxeBt7fdQCjU_zVvf63eU-lwxoOPMlahWkfQ,311
17
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ tests/test_lsmem_parser.py,sha256=mRlHTmU2ZmcxPGgcqAv_LNGs56yrwDBiw2-aHKrpuEo,793
19
+ tests/test_other_command_parser.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ jpcli-0.2.0.dist-info/LICENCE,sha256=-unHZSaIlcrVEVD56Ss5dlOvdgK682a2xitz35UlKt4,1069
21
+ jpcli-0.2.0.dist-info/METADATA,sha256=WFMCyc8oddjmsVZMLpkuF4n4-d2orJkpl9k73V46j1M,625
22
+ jpcli-0.2.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
23
+ jpcli-0.2.0.dist-info/entry_points.txt,sha256=6wCYs9scOVGFsZE-b2r2geNzy4uST0GgWyHmveiPSxE,43
24
+ jpcli-0.2.0.dist-info/top_level.txt,sha256=djdbp8mEzCmAEbrMOVEHNW4LIabBwnpLURp2dX_ZQbA,12
25
+ jpcli-0.2.0.dist-info/RECORD,,
@@ -1,6 +1,7 @@
1
1
  import unittest
2
2
  from jpcli.parsers import lsmem_parser
3
3
 
4
+
4
5
  class TestLsmemParser(unittest.TestCase):
5
6
 
6
7
  def test_parse(self):
@@ -15,5 +16,6 @@ RANGE SIZE STATE REMOVABLE BLOCK
15
16
  ]
16
17
  self.assertEqual(lsmem_parser.parse(command_output), expected_output)
17
18
 
19
+
18
20
  if __name__ == '__main__':
19
21
  unittest.main()
@@ -1,5 +0,0 @@
1
- def parse(command_output):
2
- # Implement parsing logic for the other command
3
- data = {}
4
- # Parsing logic here
5
- return data
@@ -1,15 +0,0 @@
1
- jpcli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- jpcli/main.py,sha256=yqnw53CJ6cBFtV6X1ujy3sfKGu9I3Tp9Rrrm1gcOauU,1653
3
- jpcli/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- jpcli/parsers/free_parser.py,sha256=XymIi1eafmIElMMVxS3DmlZ-oC4dcYvKmNWDm5tCEEs,721
5
- jpcli/parsers/lsmem_parser.py,sha256=EFGZISeaH9esGOnj_lYX0_biZjKnWo23dtDY9-LZ42s,745
6
- jpcli/parsers/other_command_parser.py,sha256=G2so9nFluHiyuyEDJouxuN4FHkNheyIY_laDFXxE6xM,134
7
- tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- tests/test_lsmem_parser.py,sha256=maT0mCSFyAHCMdRMl0NEa-FUE_2-MMDoYZS5W67PYZU,791
9
- tests/test_other_command_parser.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- jpcli-0.1.3.dist-info/LICENCE,sha256=-unHZSaIlcrVEVD56Ss5dlOvdgK682a2xitz35UlKt4,1069
11
- jpcli-0.1.3.dist-info/METADATA,sha256=UKRlNwr6g41gzrQT1zw2xNbiVun-CZ0NU-uoyAhu--w,625
12
- jpcli-0.1.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
13
- jpcli-0.1.3.dist-info/entry_points.txt,sha256=6wCYs9scOVGFsZE-b2r2geNzy4uST0GgWyHmveiPSxE,43
14
- jpcli-0.1.3.dist-info/top_level.txt,sha256=djdbp8mEzCmAEbrMOVEHNW4LIabBwnpLURp2dX_ZQbA,12
15
- jpcli-0.1.3.dist-info/RECORD,,
File without changes
File without changes