11import argparse
2- from contextlib import ExitStack
32from typing import List , Callable , Mapping , Optional
43
54from pybm .builders import BaseBuilder
65from pybm .command import CLICommand
76from pybm .config import PybmConfig , get_component_class
87from pybm .env_store import EnvironmentStore
9- from pybm .exceptions import PybmError
108from pybm .logging import get_logger
119from pybm .status_codes import ERROR , SUCCESS
1210
@@ -27,7 +25,7 @@ class EnvCommand(CLICommand):
2725 " or: pybm env install <identifier> <packages> [<options>]\n "
2826 " or: pybm env uninstall <identifier> <packages> [<options>]\n "
2927 " or: pybm env list\n "
30- " or: pybm env update <env> <attr> <value >\n "
28+ " or: pybm env switch <env> <ref >\n "
3129 )
3230
3331 def __init__ (self ):
@@ -93,12 +91,12 @@ def add_arguments(self, subcommand: str = None):
9391 "environment. Raises an error if the path does not exist or is not "
9492 "recognized as a valid Python virtual environment." ,
9593 )
96- elif subcommand in [ "delete" , "install" , "uninstall" ] :
94+ elif subcommand == "delete" :
9795 self .parser .add_argument (
9896 "identifier" ,
9997 metavar = "<id>" ,
100- help = "Information that uniquely identifies the environment. "
101- "Can be name, checked out commit/branch/tag, or worktree directory." ,
98+ help = "Information that uniquely identifies the environment. Can be "
99+ "name, checked out commit/branch/tag, or worktree directory." ,
102100 )
103101 if subcommand == "delete" :
104102 self .parser .add_argument (
@@ -107,19 +105,35 @@ def add_arguments(self, subcommand: str = None):
107105 action = "store_true" ,
108106 help = "Force worktree removal, including untracked files." ,
109107 )
110- else :
111- self .parser .add_argument (
112- "packages" ,
113- nargs = "*" ,
114- default = None ,
115- metavar = "<packages>" ,
116- help = "Package dependencies to install into the new virtual "
117- "environment." ,
118- )
108+ elif subcommand in ["install" , "uninstall" ]:
109+ self .parser .add_argument (
110+ "name" ,
111+ metavar = "<name>" ,
112+ help = "Information that uniquely identifies the environment. Can be "
113+ "name, checked out (partial) commit/branch/tag, or worktree directory." ,
114+ )
115+ self .parser .add_argument (
116+ "packages" ,
117+ nargs = "*" ,
118+ default = None ,
119+ metavar = "<packages>" ,
120+ help = "Package dependencies to install into / uninstall from the new "
121+ "virtual environment." ,
122+ )
119123 elif subcommand == "list" :
120124 pass
121- elif subcommand == "update" :
122- pass
125+ elif subcommand == "switch" :
126+ self .parser .add_argument (
127+ "name" ,
128+ metavar = "<name>" ,
129+ help = "Name of the benchmark environment to switch checkout for." ,
130+ )
131+ self .parser .add_argument (
132+ "ref" ,
133+ metavar = "<ref>" ,
134+ help = "New git reference to check out in the chosen environment. Can "
135+ "be a branch name, tag, or (partial) commit SHA." ,
136+ )
123137
124138 assert subcommand is not None , "no valid subcommand specified"
125139
@@ -134,7 +148,7 @@ def add_arguments(self, subcommand: str = None):
134148 )
135149 builder_group = self .parser .add_argument_group (builder_group_desc )
136150
137- # add builder-specific options into the group
151+ # add builder-specific options
138152 for arg in builder_args :
139153 builder_group .add_argument (arg .pop ("flags" ), ** arg )
140154
@@ -191,53 +205,33 @@ def install(self, options: argparse.Namespace):
191205 verbose : bool = option_dict .pop ("verbose" )
192206
193207 # env name / git worktree info
194- identifier : str = option_dict .pop ("identifier" )
208+ info : str = option_dict .pop ("identifier" )
195209
196- # builder arguments
197210 packages : Optional [List [str ]] = option_dict .pop ("packages" )
198211
199- builder : BaseBuilder = get_component_class ("builder" , config = self .config )
200-
201212 env_store = EnvironmentStore (config = self .config , verbose = verbose )
202213
203- target_env = env_store .get (identifier )
204-
205- with ExitStack () as ctx :
206- ctx .callback (env_store .save )
207- builder .install (
208- spec = target_env .python ,
209- packages = packages ,
210- verbose = verbose ,
211- ** option_dict ,
212- )
214+ env_store .install (info = info , packages = packages , verbose = verbose , ** option_dict )
213215
214216 return SUCCESS
215217
216218 def uninstall (self , options : argparse .Namespace ):
217219 option_dict = vars (options )
218220
219- # verbosity
220221 verbose : bool = option_dict .pop ("verbose" )
221222
222- identifier : str = option_dict .pop ("identifier" )
223+ info : str = option_dict .pop ("identifier" )
223224
224- # builder arguments
225225 packages : List [str ] = option_dict .pop ("packages" )
226226
227- builder : BaseBuilder = get_component_class ("builder" , config = self .config )
228-
229227 env_store = EnvironmentStore (config = self .config , verbose = verbose )
230228
231- target_env = env_store .get (identifier )
232-
233- with ExitStack () as ctx :
234- ctx .callback (env_store .save )
235- builder .uninstall (
236- spec = target_env .python ,
237- packages = packages ,
238- verbose = verbose ,
239- ** option_dict ,
240- )
229+ env_store .uninstall (
230+ info = info ,
231+ packages = packages ,
232+ verbose = verbose ,
233+ ** option_dict ,
234+ )
241235
242236 return SUCCESS
243237
@@ -249,8 +243,13 @@ def list(self, options: argparse.Namespace):
249243
250244 return SUCCESS
251245
252- def update (self , options : argparse .Namespace ):
253- raise PybmError ("env updating is not implemented yet." )
246+ def switch (self , options : argparse .Namespace ):
247+ name : str = options .name
248+ ref : str = options .ref
249+ verbose : bool = options .verbose
250+
251+ env_store = EnvironmentStore (config = self .config , verbose = verbose )
252+ env_store .switch (name = name , ref = ref )
254253
255254 def run (self , args : List [str ]):
256255 logger .debug (f"Running command: `{ self .format_call (args )} `" )
@@ -261,7 +260,7 @@ def run(self, args: List[str]):
261260 "install" : self .install ,
262261 "uninstall" : self .uninstall ,
263262 "list" : self .list ,
264- "update " : self .update ,
263+ "switch " : self .switch ,
265264 }
266265
267266 if not args or args [0 ] not in subcommand_handlers :
0 commit comments