autoverse-cli 0.25.1__py3-none-any.whl → 0.26.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autoverse-cli
3
- Version: 0.25.1
3
+ Version: 0.26.0
4
4
  Summary: The Autoverse CLI
5
5
  Author-email: Dan Kamrath <dan.kamrath@autonomalabs.com>
6
6
  License: # End-User License Agreement (EULA) of the Autonoma AutoVerse CLI
@@ -43,8 +43,49 @@ Description-Content-Type: text/markdown
43
43
  License-File: LICENSE
44
44
  Requires-Dist: boto3
45
45
  Requires-Dist: cantools
46
+ Requires-Dist: argcomplete
46
47
  Dynamic: license-file
47
48
 
48
49
  # Autoverse CLI
49
50
 
50
51
  The new implementation of the Autoverse CLI
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ pip install autoverse-cli
57
+ ```
58
+
59
+ ## Shell Completion
60
+
61
+ To enable tab completion for the `avrs` command, run:
62
+
63
+ ```bash
64
+ avrs --install-completion
65
+ ```
66
+
67
+ Then reload your shell:
68
+
69
+ ```bash
70
+ source ~/.bashrc # or ~/.zshrc, ~/.config/fish/config.fish, etc.
71
+ ```
72
+
73
+ For full details, see [SHELL_COMPLETION.md](SHELL_COMPLETION.md).
74
+
75
+ ### Supported Shells
76
+
77
+ - Bash
78
+ - Zsh
79
+ - Fish
80
+ - Tcsh
81
+
82
+ ### Quick Usage Examples
83
+
84
+ ```bash
85
+ # List all available commands
86
+ avrs <TAB>
87
+
88
+ # Complete subcommand arguments
89
+ avrs launcher <TAB>
90
+ avrs restart <TAB>
91
+ ```
@@ -1,8 +1,8 @@
1
- autoverse_cli-0.25.1.dist-info/licenses/LICENSE,sha256=d4eWXho-u18HkBsX4K21uHX_bBb2UXZSrJdsb7Z_JlM,2647
1
+ autoverse_cli-0.26.0.dist-info/licenses/LICENSE,sha256=d4eWXho-u18HkBsX4K21uHX_bBb2UXZSrJdsb7Z_JlM,2647
2
2
  avrs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- avrs/app_version.py,sha256=2sBfA7DAmJHuyITvNdre0lXwh1mMU29hvS8bqyR3e0Y,856
3
+ avrs/app_version.py,sha256=UUvS1I1VuMQg2VBP8WWwCCptM3e6LCz2PKJqw5Zt-TY,856
4
4
  avrs/argparse_help.py,sha256=EoEaohGXZXqJvs1dFEzbo9vh47CYdHdSY2Im2Ps2iFo,945
5
- avrs/avrs.py,sha256=SrsLChcmXOmLq81ry3XoGh1Kvc1xVZeLpRz_7XtM9xM,5050
5
+ avrs/avrs.py,sha256=pQHc8KLAD0hCxpBoNbXOgj2Et3qiqxSMKyAXFLwWFjE,5787
6
6
  avrs/can_tool.py,sha256=IBoctKobBJ3wCq4ZdtuXuXH4AMEUxazCfYT6YP0Luw8,7161
7
7
  avrs/can_tool_util.py,sha256=G3q21dTGMLc09SDq_RieoW7kSn-kXPkXxPDjavPh4hQ,7710
8
8
  avrs/cfg.py,sha256=kMn08Z4Ms1PAu2-U1QI8weEJeIVEppP4A4_tFfwnjtg,2924
@@ -13,6 +13,7 @@ avrs/race_cloud_bridge_can.py,sha256=K3is7GFzWo2KBojr6V65kz138UfkVFXXofVxSAziArY
13
13
  avrs/race_cloud_cfg_util.py,sha256=TF_gsP7c_39MKs1CyzeXkTH-Fwyd8wLkFkMbqQVmdeo,12066
14
14
  avrs/race_cloud_fwd_api.py,sha256=jB4kt6Shu9Pj96WPVjK790PZjucYxmuHjjVKczQfyZI,1620
15
15
  avrs/race_cloud_util.py,sha256=g1gCxmK-8n32aNj0NWEiZr79s1rB0EYbGmNLabsIW0U,14297
16
+ avrs/shell_completion.py,sha256=_IM85ADKQHYNMlTa1_nhnYWsgdOzRQ7tIFHxAT6EWWA,4298
16
17
  avrs/simconfig.py,sha256=UZc4FrxVHUkk2e9IglSpuojXkaL_nPrJW7trbEGgOOo,2907
17
18
  avrs/simconfig_util.py,sha256=EDsIwMZeoOm-oyiktVgvKRKjTZtnFyPDc3dMFug7LH0,6044
18
19
  avrs/tests.py,sha256=3JeYBjn0tRqHXERDROfzmYuW1KXeCcKur5Bw-EIegto,153
@@ -43,8 +44,8 @@ avrs/requests/toggle_hud.py,sha256=sV5t5QZc4uvRihPVk8jEKZiQNsyF9tsUwq5b4jjZplc,3
43
44
  avrs/requests/vd.py,sha256=Rd0mCc89m2yKjftVf0cMHMFbJG4iFd09KzrI-DsCLgI,2606
44
45
  avrs/requests/vehicle_input.py,sha256=R1b1xkRtOBkwyU6OSN4bWVlYsIUroZG0WKbYbc4pEH8,729
45
46
  avrs/requests/vehicle_replay.py,sha256=7HPfVLjSLNbOyzU77Bz29qpHqRsMUAIWvnwvnNiw2nk,15026
46
- autoverse_cli-0.25.1.dist-info/METADATA,sha256=iKZVJW4ZyKpEzbJa7oJGLfW8Za6TogklCbzjwS04ZRY,3364
47
- autoverse_cli-0.25.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
48
- autoverse_cli-0.25.1.dist-info/entry_points.txt,sha256=Cb9qsUyU5AKkklehCcvtfT0-N3SXbUEqvjze4iEU5kE,40
49
- autoverse_cli-0.25.1.dist-info/top_level.txt,sha256=-AJO2e4MCVej6hY0U84pu5NfMeMW5qaAPSMisDT5rmA,5
50
- autoverse_cli-0.25.1.dist-info/RECORD,,
47
+ autoverse_cli-0.26.0.dist-info/METADATA,sha256=bZb69UQraajrTSExXiQiXJN0KOSYivme3MNklu2stl4,3935
48
+ autoverse_cli-0.26.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
49
+ autoverse_cli-0.26.0.dist-info/entry_points.txt,sha256=Cb9qsUyU5AKkklehCcvtfT0-N3SXbUEqvjze4iEU5kE,40
50
+ autoverse_cli-0.26.0.dist-info/top_level.txt,sha256=-AJO2e4MCVej6hY0U84pu5NfMeMW5qaAPSMisDT5rmA,5
51
+ autoverse_cli-0.26.0.dist-info/RECORD,,
avrs/app_version.py CHANGED
@@ -2,7 +2,7 @@ import http.client
2
2
  import json
3
3
 
4
4
  def get_app_version():
5
- return '0.25.1'
5
+ return '0.26.0'
6
6
 
7
7
  def check_app_is_latest():
8
8
  pass
avrs/avrs.py CHANGED
@@ -2,6 +2,7 @@
2
2
  import logging
3
3
  import argparse
4
4
  import os
5
+ import argcomplete
5
6
 
6
7
  from argparse import RawDescriptionHelpFormatter
7
8
  from argparse import RawTextHelpFormatter
@@ -12,6 +13,7 @@ from avrs.launcher import *
12
13
  from avrs.can_tool import *
13
14
  from avrs.race_cloud import *
14
15
  from avrs.argparse_help import *
16
+ from avrs.shell_completion import install_completion, uninstall_completion
15
17
 
16
18
  from avrs.requests.move_to_landmark import MoveToLandmarkRequest
17
19
  from avrs.requests.restart import Restart
@@ -99,14 +101,23 @@ def main():
99
101
  action='store_true',
100
102
  help='request verbose output')
101
103
 
102
- sps = parser.add_subparsers(required=True, help='sub-command help')
104
+ parser.add_argument(
105
+ '--install-completion',
106
+ action='store_true',
107
+ help='install shell completion for avrs CLI')
108
+
109
+ parser.add_argument(
110
+ '--uninstall-completion',
111
+ action='store_true',
112
+ help='uninstall shell completion for avrs CLI')
113
+
114
+ sps = parser.add_subparsers(required=False, help='sub-command help')
103
115
 
104
116
  cfg = load_cfg('avrs')
105
117
  check_app_is_latest()
106
118
 
107
119
  AvrsLauncher(sps, cfg)
108
120
 
109
-
110
121
  MoveToLandmarkRequest(sps, cfg)
111
122
  Restart(sps, cfg)
112
123
  ResetToTrack(sps, cfg)
@@ -150,8 +161,23 @@ def main():
150
161
  if os.environ.get('AVRS_GEN_DOCS', '0') == '1':
151
162
  generate_argparse_docs(parser)
152
163
 
164
+ argcomplete.autocomplete(parser)
153
165
  args = parser.parse_args()
154
- args.func(args)
166
+
167
+ # Handle completion installation/uninstallation
168
+ if args.install_completion:
169
+ install_completion()
170
+ return
171
+
172
+ if args.uninstall_completion:
173
+ uninstall_completion()
174
+ return
175
+
176
+ # Handle subcommands
177
+ if hasattr(args, 'func'):
178
+ args.func(args)
179
+ else:
180
+ parser.print_help()
155
181
 
156
182
  if __name__ == '__main__':
157
183
  main()
@@ -0,0 +1,121 @@
1
+ import os
2
+ import sys
3
+ import subprocess
4
+ from pathlib import Path
5
+
6
+ def get_shell_name():
7
+ """Detect the current shell from SHELL environment variable or parent process."""
8
+ shell = os.environ.get('SHELL', '')
9
+ if shell:
10
+ return os.path.basename(shell)
11
+
12
+ # Fallback: try to get parent shell
13
+ try:
14
+ parent_pid = os.getppid()
15
+ with open(f'/proc/{parent_pid}/comm', 'r') as f:
16
+ return f.read().strip()
17
+ except:
18
+ return 'bash'
19
+
20
+ def get_shell_config_file():
21
+ """Get the config file path for the detected shell."""
22
+ shell = get_shell_name()
23
+ home = str(Path.home())
24
+
25
+ if 'zsh' in shell:
26
+ return os.path.join(home, '.zshrc')
27
+ elif 'fish' in shell:
28
+ return os.path.join(home, '.config/fish/config.fish')
29
+ elif 'tcsh' in shell:
30
+ return os.path.join(home, '.tcshrc')
31
+ else: # bash and others
32
+ return os.path.join(home, '.bashrc')
33
+
34
+ def get_completion_command():
35
+ """Get the shell-specific completion registration command."""
36
+ shell = get_shell_name()
37
+
38
+ # Try to use register-python-argcomplete if available, fall back to register-python-argcomplete3
39
+ # This makes it compatible with both pip-installed and system-package versions
40
+ register_cmd = "register-python-argcomplete"
41
+
42
+ if 'zsh' in shell:
43
+ return f'eval "$({register_cmd} --shell zsh avrs 2>/dev/null || {register_cmd}3 --shell zsh avrs)"'
44
+ elif 'fish' in shell:
45
+ return f'{register_cmd} --shell fish avrs 2>/dev/null | source || {register_cmd}3 --shell fish avrs | source'
46
+ elif 'tcsh' in shell:
47
+ return f'eval "$({register_cmd} --shell tcsh avrs 2>/dev/null || {register_cmd}3 --shell tcsh avrs)"'
48
+ else: # bash
49
+ return f'eval "$({register_cmd} avrs 2>/dev/null || {register_cmd}3 avrs)"'
50
+
51
+ def install_completion():
52
+ """Install shell completion for the avrs CLI."""
53
+ shell = get_shell_name()
54
+ config_file = get_shell_config_file()
55
+ completion_command = get_completion_command()
56
+
57
+ print(f"Installing shell completion for {shell}...")
58
+
59
+ # Check if completion already installed
60
+ if os.path.exists(config_file):
61
+ with open(config_file, 'r') as f:
62
+ content = f.read()
63
+ if 'register-python-argcomplete' in content and 'avrs' in content:
64
+ print(f"✓ Completion already installed in {config_file}")
65
+ return True
66
+
67
+ # Ensure config file exists
68
+ Path(config_file).parent.mkdir(parents=True, exist_ok=True)
69
+
70
+ # Append completion command
71
+ try:
72
+ with open(config_file, 'a') as f:
73
+ f.write('\n\n# avrs CLI completion\n')
74
+ f.write(completion_command + '\n')
75
+ print(f"✓ Completion installed successfully!")
76
+ print(f"✓ Added to {config_file}")
77
+ print(f"\nTo activate completion in current shell, run:")
78
+ print(f" source {config_file}")
79
+ return True
80
+ except Exception as e:
81
+ print(f"✗ Error installing completion: {e}")
82
+ print(f"\nManually add this line to {config_file}:")
83
+ print(f" {completion_command}")
84
+ return False
85
+
86
+ def uninstall_completion():
87
+ """Remove shell completion for the avrs CLI."""
88
+ shell = get_shell_name()
89
+ config_file = get_shell_config_file()
90
+
91
+ print(f"Uninstalling shell completion from {config_file}...")
92
+
93
+ if not os.path.exists(config_file):
94
+ print("Config file not found.")
95
+ return False
96
+
97
+ try:
98
+ with open(config_file, 'r') as f:
99
+ lines = f.readlines()
100
+
101
+ # Filter out avrs completion lines
102
+ new_lines = [
103
+ line for line in lines
104
+ if 'register-python-argcomplete' not in line or 'avrs' not in line
105
+ ]
106
+
107
+ # Also remove the comment line if it's there
108
+ filtered_lines = []
109
+ for i, line in enumerate(new_lines):
110
+ if line.strip() == '# avrs CLI completion':
111
+ continue
112
+ filtered_lines.append(line)
113
+
114
+ with open(config_file, 'w') as f:
115
+ f.writelines(filtered_lines)
116
+
117
+ print(f"✓ Completion uninstalled successfully!")
118
+ return True
119
+ except Exception as e:
120
+ print(f"✗ Error uninstalling completion: {e}")
121
+ return False