66import argparse
77from .core import omnipkg , ConfigManager
88from pathlib import Path
9+ import textwrap
910
1011def print_header (title ):
1112 """Prints a consistent, pretty header for CLI sections."""
1213 print ("\n " + "=" * 60 )
1314 print (f" 🚀 { title } " )
1415 print ("=" * 60 )
1516
16- import textwrap
17-
1817def create_parser ():
1918 """Creates and configures the argument parser."""
20- # This formatter_class is key to making our new help text look good.
21- # The epilog provides examples of the most important commands.
2219 parser = argparse .ArgumentParser (
2320 prog = 'omnipkg' ,
2421 description = 'The intelligent Python package manager that solves dependency hell.' ,
25- formatter_class = argparse .RawTextHelpFormatter , # Prevents argparse from messing up our formatting
22+ formatter_class = argparse .RawTextHelpFormatter ,
2623 epilog = textwrap .dedent ('''\
2724
2825 Common Commands:
2926 omnipkg install <package> Install a package with downgrade protection.
3027 omnipkg list See all installed packages and their health.
3128 omnipkg status Check the health of your multi-version environment.
3229 omnipkg info <package> Get a detailed dashboard for a specific package.
33- omnipkg demo Run the interactive showcase to see the magic .
30+ omnipkg stress-test Run the ultimate compatibility stress test .
3431 ''' )
3532 )
3633
3734 subparsers = parser .add_subparsers (dest = 'command' , help = 'All available commands:' , required = True )
3835
3936 install_parser = subparsers .add_parser ('install' , help = 'Install packages (with downgrade protection)' )
40- # Make 'packages' optional (nargs='*') to allow using -r instead
4137 install_parser .add_argument ('packages' , nargs = '*' , help = 'Packages to install (e.g., "requests==2.25.1")' )
42- # Add the new -r/--requirement flag
43- install_parser .add_argument (
44- '-r' , '--requirement' ,
45- help = 'Install from the given requirements file.' ,
46- metavar = 'FILE'
47- )
38+ install_parser .add_argument ('-r' , '--requirement' , help = 'Install from the given requirements file.' , metavar = 'FILE' )
4839
4940 uninstall_parser = subparsers .add_parser ('uninstall' , help = 'Uninstall packages from main env or bubbles' )
50- uninstall_parser .add_argument ('packages' , nargs = '+' , help = 'Packages to uninstall (e.g., "requests" or "requests==2.25.1") ' )
41+ uninstall_parser .add_argument ('packages' , nargs = '+' , help = 'Packages to uninstall' )
5142 uninstall_parser .add_argument ('--yes' , '-y' , action = 'store_true' , help = 'Skip confirmation prompts' )
5243
53- info_parser = subparsers .add_parser ('info' , help = 'Show detailed package information with interactive version selection ' )
44+ info_parser = subparsers .add_parser ('info' , help = 'Show detailed package information' )
5445 info_parser .add_argument ('package' , help = 'Package name to inspect' )
5546 info_parser .add_argument ('--version' , default = 'active' , help = 'Specific version to inspect' )
5647
5748 revert_parser = subparsers .add_parser ('revert' , help = "Revert environment to the last known good state" )
58- revert_parser .add_argument ('--yes' , '-y' , action = 'store_true' , help = 'Skip confirmation and revert immediately ' )
49+ revert_parser .add_argument ('--yes' , '-y' , action = 'store_true' , help = 'Skip confirmation' )
5950
6051 list_parser = subparsers .add_parser ('list' , help = 'List installed packages' )
61- list_parser .add_argument ('filter' , nargs = '?' , help = 'Optional filter pattern for package names' )
52+ list_parser .add_argument ('filter' , nargs = '?' , help = 'Optional filter for package names' )
6253
6354 status_parser = subparsers .add_parser ('status' , help = 'Show multi-version system status' )
6455
@@ -69,80 +60,43 @@ def create_parser():
6960 reset_parser = subparsers .add_parser ('reset' , help = 'DELETE and rebuild the omnipkg knowledge base in Redis' )
7061 reset_parser .add_argument ('--yes' , '-y' , action = 'store_true' , help = 'Skip confirmation' )
7162
72- rebuild_parser = subparsers .add_parser ('rebuild-kb' , help = 'Force a full rebuild of the knowledge base without deleting ' )
73- rebuild_parser .add_argument ('--force' , '-f' , action = 'store_true' , help = 'Ignore cache and force re-processing of all metadata ' )
63+ rebuild_parser = subparsers .add_parser ('rebuild-kb' , help = 'Force a full rebuild of the knowledge base' )
64+ rebuild_parser .add_argument ('--force' , '-f' , action = 'store_true' , help = 'Ignore cache and force re-processing' )
7465
7566 return parser
7667
7768def main ():
7869 """The main entry point for the CLI."""
79-
80- # Handle the case where 'omnipkg' is run with no arguments
8170 if len (sys .argv ) == 1 :
8271 cm = ConfigManager ()
83- if not cm .config_path .exists ():
84- cm ._first_time_setup ()
85- print ("\n " + "=" * 50 )
86- print ("🚀 Welcome to omnipkg! Your setup is complete." )
87- print ("To see the magic in action, we highly recommend running the demo:" )
88- print ("\n omnipkg demo\n " )
89- print ("=" * 50 )
90- else :
91- print ("👋 Welcome back to omnipkg!" )
92- print (" Run `omnipkg status` to see your environment." )
93- print (" Run `omnipkg demo` for a showcase of features." )
94- print (" Run `omnipkg --help` for all commands." )
72+ # This part for running 'omnipkg' with no arguments is fine.
73+ print ("👋 Welcome to omnipkg! Run `omnipkg --help` for commands." )
9574 return 0
9675
9776 parser = create_parser ()
9877 args = parser .parse_args ()
99-
100- # First, create the config manager to load/create the config
101- cm = ConfigManager ()
10278
103- # Now, create the main instance, PASSING IN the loaded config
79+ cm = ConfigManager ()
10480 pkg_instance = omnipkg (cm .config )
105- try :
106- # In omnipkg/cli.py -> main()
10781
82+ try :
10883 if args .command == 'install' :
10984 packages_to_process = []
110-
11185 if args .requirement :
112- # User provided a requirements file
11386 req_path = Path (args .requirement )
11487 if not req_path .is_file ():
11588 print (f"❌ Error: Requirements file not found at '{ req_path } '" )
11689 return 1
117-
118- print (f"📄 Reading packages from { req_path .name } ..." )
119- # In omnipkg/cli.py -> main()
120-
12190 with open (req_path , 'r' ) as f :
122- # Parse the file, handling inline comments and empty lines
123- packages_to_process = []
124- for line in f :
125- # Get the part before any comment and strip whitespace
126- clean_line = line .split ('#' )[0 ].strip ()
127- # Only add it to our list if it's not an empty string
128- if clean_line :
129- packages_to_process .append (clean_line )
130-
91+ packages_to_process = [line .split ('#' )[0 ].strip () for line in f if line .split ('#' )[0 ].strip ()]
13192 elif args .packages :
132- # User provided packages directly on the command line
13393 packages_to_process = args .packages
134-
13594 else :
136- # No packages or file provided
137- print ("❌ Error: You must either specify packages to install or use the -r flag." )
138- print (" Example: `omnipkg install requests` or `omnipkg install -r requirements.txt`" )
95+ print ("❌ Error: You must specify packages or use -r. Ex: `omnipkg install requests`" )
13996 return 1
140-
141- # The magic happens here: pass the list to your existing core logic
14297 return pkg_instance .smart_install (packages_to_process )
14398 elif args .command == 'uninstall' :
14499 return pkg_instance .smart_uninstall (args .packages , force = args .yes )
145-
146100 elif args .command == 'revert' :
147101 return pkg_instance .revert_to_last_known_good (force = args .yes )
148102 elif args .command == 'info' :
@@ -151,21 +105,31 @@ def main():
151105 return pkg_instance .list_packages (args .filter )
152106 elif args .command == 'status' :
153107 return pkg_instance .show_multiversion_status ()
108+
109+ # ### MODIFIED: Fix for the TypeError ###
154110 elif args .command == 'demo' :
155- from .demo import run_demo
156- return run_demo ()
111+ print_header ("Demo Under Construction!" )
112+ print ("The interactive demo is still being polished." )
113+ print ("For now, we'll run the 'stress-test' to showcase omnipkg's power." )
114+ # Fall-through to the stress-test logic
115+ from . import stress_test
116+ if input ("\n Proceed with the stress test? (y/n): " ).lower () != 'y' :
117+ print ("Stress test cancelled." )
118+ return 0
119+ stress_test .run () # <-- CORRECTED: Pass no arguments
120+ return 0
121+
157122 elif args .command == 'stress-test' :
158123 from . import stress_test
159124 print_header ("omnipkg Ultimate Stress Test" )
160125 print ("This test will install, bubble, and test multiple large scientific packages." )
161126 print ("\n ⚠️ This will download several hundred MB and may take several minutes." )
162-
163127 if input ("\n Proceed with the stress test? (y/n): " ).lower () != 'y' :
164128 print ("Stress test cancelled." )
165129 return 0
166-
167- stress_test .run ()
130+ stress_test .run () # <-- CORRECTED: Pass no arguments
168131 return 0
132+
169133 elif args .command == 'reset' :
170134 return pkg_instance .reset_knowledge_base (force = args .yes )
171135 elif args .command == 'rebuild-kb' :
0 commit comments