From b97837839216d2921b590271bbf4d00291969ffd Mon Sep 17 00:00:00 2001 From: david-sarah Date: Sun, 24 Jul 2011 15:54:40 -0700 Subject: [PATCH] Fix the help synopses of CLI commands to include [options] in the right place. fixes #1359, fixes #636 --- src/allmydata/scripts/cli.py | 47 ++++++++----- src/allmydata/scripts/common.py | 6 ++ src/allmydata/scripts/create_node.py | 6 +- src/allmydata/scripts/startstop_node.py | 8 +-- src/allmydata/test/test_cli.py | 87 +++++++++++++++++++------ 5 files changed, 108 insertions(+), 46 deletions(-) diff --git a/src/allmydata/scripts/cli.py b/src/allmydata/scripts/cli.py index 1713002c..2a5f6611 100644 --- a/src/allmydata/scripts/cli.py +++ b/src/allmydata/scripts/cli.py @@ -52,6 +52,10 @@ class VDriveOptions(BaseOptions): class MakeDirectoryOptions(VDriveOptions): def parseArgs(self, where=""): self.where = argv_to_unicode(where) + + def getSynopsis(self): + return "Usage: %s mkdir [options] [REMOTE_DIR]" % (self.command_name,) + longdesc = """Create a new directory, either unlinked or as a subdirectory.""" class AddAliasOptions(VDriveOptions): @@ -62,7 +66,7 @@ class AddAliasOptions(VDriveOptions): self.cap = cap def getSynopsis(self): - return "Usage: %s add-alias ALIAS[:] DIRCAP" % (os.path.basename(sys.argv[0]),) + return "Usage: %s add-alias [options] ALIAS[:] DIRCAP" % (self.command_name,) longdesc = """Add a new alias for an existing directory.""" @@ -73,11 +77,14 @@ class CreateAliasOptions(VDriveOptions): self.alias = self.alias[:-1] def getSynopsis(self): - return "Usage: %s create-alias ALIAS[:]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s create-alias [options] ALIAS[:]" % (self.command_name,) longdesc = """Create a new directory and add an alias for it.""" -class ListAliasOptions(VDriveOptions): +class ListAliasesOptions(VDriveOptions): + def getSynopsis(self): + return "Usage: %s list-aliases [options]" % (self.command_name,) + longdesc = """Display a table of all configured aliases.""" class ListOptions(VDriveOptions): @@ -135,7 +142,7 @@ class GetOptions(VDriveOptions): self.to_file = None def getSynopsis(self): - return "Usage: %s get REMOTE_FILE LOCAL_FILE" % (os.path.basename(sys.argv[0]),) + return "Usage: %s get [options] REMOTE_FILE LOCAL_FILE" % (self.command_name,) longdesc = """ Retrieve a file from the grid and write it to the local filesystem. If @@ -174,7 +181,7 @@ class PutOptions(VDriveOptions): self.from_file = None def getSynopsis(self): - return "Usage: %s put LOCAL_FILE REMOTE_FILE" % (os.path.basename(sys.argv[0]),) + return "Usage: %s put [options] LOCAL_FILE REMOTE_FILE" % (self.command_name,) longdesc = """ Put a file into the grid, copying its contents from the local filesystem. @@ -205,13 +212,16 @@ class CpOptions(VDriveOptions): "When copying to local files, write out filecaps instead of actual " "data (only useful for debugging and tree-comparison purposes)."), ] + def parseArgs(self, *args): if len(args) < 2: raise usage.UsageError("cp requires at least two arguments") self.sources = map(argv_to_unicode, args[:-1]) self.destination = argv_to_unicode(args[-1]) + def getSynopsis(self): - return "Usage: tahoe [options] cp FROM.. TO" + return "Usage: tahoe cp [options] FROM.. TO" + longdesc = """ Use 'tahoe cp' to copy files between a local filesystem and a Tahoe grid. Any FROM/TO arguments that begin with an alias indicate Tahoe-side @@ -242,11 +252,11 @@ class RmOptions(VDriveOptions): self.where = argv_to_unicode(where) def getSynopsis(self): - return "Usage: %s rm REMOTE_FILE" % (os.path.basename(sys.argv[0]),) + return "Usage: %s rm [options] REMOTE_FILE" % (self.command_name,) class UnlinkOptions(RmOptions): def getSynopsis(self): - return "Usage: %s unlink REMOTE_FILE" % (os.path.basename(sys.argv[0]),) + return "Usage: %s unlink [options] REMOTE_FILE" % (self.command_name,) class MvOptions(VDriveOptions): def parseArgs(self, frompath, topath): @@ -254,7 +264,8 @@ class MvOptions(VDriveOptions): self.to_file = argv_to_unicode(topath) def getSynopsis(self): - return "Usage: %s mv FROM TO" % (os.path.basename(sys.argv[0]),) + return "Usage: %s mv [options] FROM TO" % (self.command_name,) + longdesc = """ Use 'tahoe mv' to move files that are already on the grid elsewhere on the grid, e.g., 'tahoe mv alias:some_file alias:new_file'. @@ -273,7 +284,7 @@ class LnOptions(VDriveOptions): self.to_file = argv_to_unicode(topath) def getSynopsis(self): - return "Usage: %s ln FROM_LINK TO_LINK" % (os.path.basename(sys.argv[0]),) + return "Usage: %s ln [options] FROM_LINK TO_LINK" % (self.command_name,) longdesc = """ Use 'tahoe ln' to duplicate a link (directory entry) already on the grid @@ -319,8 +330,8 @@ class BackupOptions(VDriveOptions): self.from_dir = argv_to_unicode(localdir) self.to_dir = argv_to_unicode(topath) - def getSynopsis(Self): - return "Usage: %s backup FROM ALIAS:TO" % os.path.basename(sys.argv[0]) + def getSynopsis(self): + return "Usage: %s backup [options] FROM ALIAS:TO" % (self.command_name,) def opt_exclude(self, pattern): """Ignore files matching a glob pattern. You may give multiple @@ -378,7 +389,7 @@ class WebopenOptions(VDriveOptions): self.where = argv_to_unicode(where) def getSynopsis(self): - return "Usage: %s webopen [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s webopen [options] [ALIAS:PATH]" % (self.command_name,) longdesc = """Open a web browser to the contents of some file or directory on the grid. When run without arguments, open the Welcome @@ -395,7 +406,7 @@ class ManifestOptions(VDriveOptions): self.where = argv_to_unicode(where) def getSynopsis(self): - return "Usage: %s manifest [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s manifest [options] [ALIAS:PATH]" % (self.command_name,) longdesc = """Print a list of all files and directories reachable from the given starting point.""" @@ -408,7 +419,7 @@ class StatsOptions(VDriveOptions): self.where = argv_to_unicode(where) def getSynopsis(self): - return "Usage: %s stats [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s stats [options] [ALIAS:PATH]" % (self.command_name,) longdesc = """Print statistics about of all files and directories reachable from the given starting point.""" @@ -424,7 +435,7 @@ class CheckOptions(VDriveOptions): self.where = argv_to_unicode(where) def getSynopsis(self): - return "Usage: %s check [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s check [options] [ALIAS:PATH]" % (self.command_name,) longdesc = """ Check a single file or directory: count how many shares are available and @@ -443,7 +454,7 @@ class DeepCheckOptions(VDriveOptions): self.where = argv_to_unicode(where) def getSynopsis(self): - return "Usage: %s deep-check [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s deep-check [options] [ALIAS:PATH]" % (self.command_name,) longdesc = """ Check all files and directories reachable from the given starting point @@ -454,7 +465,7 @@ subCommands = [ ["mkdir", None, MakeDirectoryOptions, "Create a new directory."], ["add-alias", None, AddAliasOptions, "Add a new alias cap."], ["create-alias", None, CreateAliasOptions, "Create a new alias cap."], - ["list-aliases", None, ListAliasOptions, "List all alias caps."], + ["list-aliases", None, ListAliasesOptions, "List all alias caps."], ["ls", None, ListOptions, "List a directory."], ["get", None, GetOptions, "Retrieve a file from the grid."], ["put", None, PutOptions, "Upload a file into the grid."], diff --git a/src/allmydata/scripts/common.py b/src/allmydata/scripts/common.py index ac5432b3..cd545c3c 100644 --- a/src/allmydata/scripts/common.py +++ b/src/allmydata/scripts/common.py @@ -40,6 +40,12 @@ class BaseOptions(usage.Options): _default_nodedir and (" [default for most commands: " + quote_output(_default_nodedir) + "]") or "")], ] + def __init__(self): + super(BaseOptions, self).__init__() + self.command_name = os.path.basename(sys.argv[0]) + if self.command_name == 'trial': + self.command_name = 'tahoe' + def opt_version(self): import allmydata print >>self.stdout, allmydata.get_package_versions_string(debug=True) diff --git a/src/allmydata/scripts/create_node.py b/src/allmydata/scripts/create_node.py index 774c9737..41554fa2 100644 --- a/src/allmydata/scripts/create_node.py +++ b/src/allmydata/scripts/create_node.py @@ -17,7 +17,7 @@ class CreateClientOptions(BasedirMixin, BaseOptions): ] def getSynopsis(self): - return "Usage: %s create-client [options] [NODEDIR]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s create-client [options] [NODEDIR]" % (self.command_name,) class CreateNodeOptions(CreateClientOptions): @@ -26,7 +26,7 @@ class CreateNodeOptions(CreateClientOptions): ] def getSynopsis(self): - return "Usage: %s create-node [options] [NODEDIR]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s create-node [options] [NODEDIR]" % (self.command_name,) class CreateIntroducerOptions(BasedirMixin, BaseOptions): @@ -37,7 +37,7 @@ class CreateIntroducerOptions(BasedirMixin, BaseOptions): ] def getSynopsis(self): - return "Usage: %s create-introducer [options] NODEDIR" % (os.path.basename(sys.argv[0]),) + return "Usage: %s create-introducer [options] NODEDIR" % (self.command_name,) client_tac = """ diff --git a/src/allmydata/scripts/startstop_node.py b/src/allmydata/scripts/startstop_node.py index 9f8908bb..5045bd61 100644 --- a/src/allmydata/scripts/startstop_node.py +++ b/src/allmydata/scripts/startstop_node.py @@ -13,12 +13,12 @@ class StartOptions(BasedirMixin, BaseOptions): ] def getSynopsis(self): - return "Usage: %s start [options] [NODEDIR]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s start [options] [NODEDIR]" % (self.command_name,) class StopOptions(BasedirMixin, BaseOptions): def getSynopsis(self): - return "Usage: %s stop [options] [NODEDIR]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s stop [options] [NODEDIR]" % (self.command_name,) class RestartOptions(BasedirMixin, BaseOptions): @@ -28,7 +28,7 @@ class RestartOptions(BasedirMixin, BaseOptions): ] def getSynopsis(self): - return "Usage: %s restart [options] [NODEDIR]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s restart [options] [NODEDIR]" % (self.command_name,) class RunOptions(BasedirMixin, BaseOptions): @@ -39,7 +39,7 @@ class RunOptions(BasedirMixin, BaseOptions): ] def getSynopsis(self): - return "Usage: %s run [options] [NODEDIR]" % (os.path.basename(sys.argv[0]),) + return "Usage: %s run [options] [NODEDIR]" % (self.command_name,) def start(opts, out=sys.stdout, err=sys.stderr): diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py index 2dbbba27..33d00ba1 100644 --- a/src/allmydata/test/test_cli.py +++ b/src/allmydata/test/test_cli.py @@ -447,67 +447,112 @@ class CLI(CLITestMixin, unittest.TestCase): class Help(unittest.TestCase): - def test_get(self): help = str(cli.GetOptions()) - self.failUnless("get REMOTE_FILE LOCAL_FILE" in help, help) - self.failUnless("% tahoe get FOO |less" in help, help) + self.failUnlessIn(" get [options] REMOTE_FILE LOCAL_FILE", help) + self.failUnlessIn("% tahoe get FOO |less", help) def test_put(self): help = str(cli.PutOptions()) - self.failUnless("put LOCAL_FILE REMOTE_FILE" in help, help) - self.failUnless("% cat FILE | tahoe put" in help, help) + self.failUnlessIn(" put [options] LOCAL_FILE REMOTE_FILE", help) + self.failUnlessIn("% cat FILE | tahoe put", help) + + def test_unlink(self): + help = str(cli.UnlinkOptions()) + self.failUnlessIn(" unlink [options] REMOTE_FILE", help) def test_rm(self): help = str(cli.RmOptions()) - self.failUnless("rm REMOTE_FILE" in help, help) + self.failUnlessIn(" rm [options] REMOTE_FILE", help) def test_mv(self): help = str(cli.MvOptions()) - self.failUnless("mv FROM TO" in help, help) - self.failUnless("Use 'tahoe mv' to move files" in help) + self.failUnlessIn(" mv [options] FROM TO", help) + self.failUnlessIn("Use 'tahoe mv' to move files", help) + + def test_cp(self): + help = str(cli.CpOptions()) + self.failUnlessIn(" cp [options] FROM.. TO", help) + self.failUnlessIn("Use 'tahoe cp' to copy files", help) def test_ln(self): help = str(cli.LnOptions()) - self.failUnless("ln FROM_LINK TO_LINK" in help, help) - self.failUnless("Use 'tahoe ln' to duplicate a link" in help) + self.failUnlessIn(" ln [options] FROM_LINK TO_LINK", help) + self.failUnlessIn("Use 'tahoe ln' to duplicate a link", help) + + def test_mkdir(self): + help = str(cli.MakeDirectoryOptions()) + self.failUnlessIn(" mkdir [options] [REMOTE_DIR]", help) + self.failUnlessIn("Create a new directory", help) def test_backup(self): help = str(cli.BackupOptions()) - self.failUnless("backup FROM ALIAS:TO" in help, help) + self.failUnlessIn(" backup [options] FROM ALIAS:TO", help) def test_webopen(self): help = str(cli.WebopenOptions()) - self.failUnless("webopen [ALIAS:PATH]" in help, help) + self.failUnlessIn(" webopen [options] [ALIAS:PATH]", help) def test_manifest(self): help = str(cli.ManifestOptions()) - self.failUnless("manifest [ALIAS:PATH]" in help, help) + self.failUnlessIn(" manifest [options] [ALIAS:PATH]", help) def test_stats(self): help = str(cli.StatsOptions()) - self.failUnless("stats [ALIAS:PATH]" in help, help) + self.failUnlessIn(" stats [options] [ALIAS:PATH]", help) def test_check(self): help = str(cli.CheckOptions()) - self.failUnless("check [ALIAS:PATH]" in help, help) + self.failUnlessIn(" check [options] [ALIAS:PATH]", help) def test_deep_check(self): help = str(cli.DeepCheckOptions()) - self.failUnless("deep-check [ALIAS:PATH]" in help, help) + self.failUnlessIn(" deep-check [options] [ALIAS:PATH]", help) def test_create_alias(self): help = str(cli.CreateAliasOptions()) - self.failUnless("create-alias ALIAS[:]" in help, help) + self.failUnlessIn(" create-alias [options] ALIAS[:]", help) - def test_add_aliases(self): + def test_add_alias(self): help = str(cli.AddAliasOptions()) - self.failUnless("add-alias ALIAS[:] DIRCAP" in help, help) + self.failUnlessIn(" add-alias [options] ALIAS[:] DIRCAP", help) + + def test_list_aliases(self): + help = str(cli.ListAliasesOptions()) + self.failUnlessIn(" list-aliases [options]", help) + + def test_start(self): + help = str(startstop_node.StartOptions()) + self.failUnlessIn(" start [options] [NODEDIR]", help) + + def test_stop(self): + help = str(startstop_node.StopOptions()) + self.failUnlessIn(" stop [options] [NODEDIR]", help) + + def test_restart(self): + help = str(startstop_node.RestartOptions()) + self.failUnlessIn(" restart [options] [NODEDIR]", help) + + def test_run(self): + help = str(startstop_node.RunOptions()) + self.failUnlessIn(" run [options] [NODEDIR]", help) + + def test_create_client(self): + help = str(create_node.CreateClientOptions()) + self.failUnlessIn(" create-client [options] [NODEDIR]", help) + + def test_create_node(self): + help = str(create_node.CreateNodeOptions()) + self.failUnlessIn(" create-node [options] [NODEDIR]", help) + + def test_create_introducer(self): + help = str(create_node.CreateIntroducerOptions()) + self.failUnlessIn(" create-introducer [options] NODEDIR", help) def test_debug_trial(self): help = str(debug.TrialOptions()) - self.failUnless("debug trial [options] [[file|package|module|TestCase|testmethod]...]" in help, help) - self.failUnless("The 'tahoe debug trial' command uses the correct imports" in help, help) + self.failUnlessIn(" debug trial [options] [[file|package|module|TestCase|testmethod]...]", help) + self.failUnlessIn("The 'tahoe debug trial' command uses the correct imports", help) class CreateAlias(GridTestMixin, CLITestMixin, unittest.TestCase): -- 2.45.2