Repository: Duke-GCB/DukeDSClient

Issue:
Show the ddsclient version in help or with a --version argument
When running ddsclient, it will print a message about a newer version, but I can't find any command-line option to print the current version. Obviously I can `pip freeze` but the tool should be able to report its own version

Discussion:

Patch:
diff --git a/ddsc/cmdparser.py b/ddsc/cmdparser.py
index dd3c1bf..8cc145e 100644
--- a/ddsc/cmdparser.py
+++ b/ddsc/cmdparser.py
@@ -6,7 +6,7 @@ import argparse
 import six
 from builtins import str
 
-
+DESCRIPTION_STR = "DukeDSClient ({}) Manage projects/folders/files in the duke-data-service"
 INVALID_PATH_CHARS = (':', '/', '\\')
 
 
@@ -321,8 +321,8 @@ class CommandParser(object):
     You must register external functions to called for the various commands.
     Commands must be registered to appear in help.
     """
-    def __init__(self):
-        self.parser = argparse.ArgumentParser()
+    def __init__(self, version_str):
+        self.parser = argparse.ArgumentParser(description=DESCRIPTION_STR.format(version_str))
         _skip_config_file_permission_check(self.parser)
         self.subparsers = self.parser.add_subparsers()
         self.upload_func = None
diff --git a/ddsc/ddsclient.py b/ddsc/ddsclient.py
index cc80a70..2015f17 100644
--- a/ddsc/ddsclient.py
+++ b/ddsc/ddsclient.py
@@ -11,7 +11,7 @@ from ddsc.cmdparser import CommandParser, path_does_not_exist_or_is_empty, repla
 from ddsc.core.download import ProjectDownload
 from ddsc.core.util import ProjectDetailsList, verify_terminal_encoding
 from ddsc.core.pathfilter import PathFilter
-from ddsc.versioncheck import check_version, VersionException
+from ddsc.versioncheck import check_version, VersionException, get_internal_version_str
 from ddsc.config import create_config
 
 NO_PROJECTS_FOUND_MESSAGE = 'No projects found.'
@@ -38,7 +38,7 @@ class DDSClient(object):
         Create a parser hooking up the command methods below to be run when chosen.
         :return: CommandParser parser with commands attached.
         """
-        parser = CommandParser()
+        parser = CommandParser(get_internal_version_str())
         parser.register_list_command(self._setup_run_command(ListCommand))
         parser.register_upload_command(self._setup_run_command(UploadCommand))
         parser.register_add_user_command(self._setup_run_command(AddUserCommand))


Test patch:
diff --git a/ddsc/tests/test_cmdparser.py b/ddsc/tests/test_cmdparser.py
index 669b140..a3b2147 100644
--- a/ddsc/tests/test_cmdparser.py
+++ b/ddsc/tests/test_cmdparser.py
@@ -16,7 +16,7 @@ class TestCommandParser(TestCase):
         self.parsed_args = args
 
     def test_register_add_user_command_project_name(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_add_user_command(self.set_parsed_args)
         self.assertEqual(['add-user'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['add-user', '-p', 'myproj', '--user', 'joe123'])
@@ -24,7 +24,7 @@ class TestCommandParser(TestCase):
         self.assertEqual(None, self.parsed_args.project_id)
 
     def test_register_add_user_command_project_id(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_add_user_command(self.set_parsed_args)
         self.assertEqual(['add-user'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['add-user', '-i', '123', '--user', 'joe123'])
@@ -32,7 +32,7 @@ class TestCommandParser(TestCase):
         self.assertEqual('123', self.parsed_args.project_id)
 
     def test_register_remove_user_command_project_name(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_remove_user_command(self.set_parsed_args)
         self.assertEqual(['remove-user'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['remove-user', '-p', 'myproj', '--user', 'joe123'])
@@ -40,7 +40,7 @@ class TestCommandParser(TestCase):
         self.assertEqual(None, self.parsed_args.project_id)
 
     def test_register_remove_user_command_project_id(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_remove_user_command(self.set_parsed_args)
         self.assertEqual(['remove-user'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['remove-user', '-i', '456', '--user', 'joe123'])
@@ -48,7 +48,7 @@ class TestCommandParser(TestCase):
         self.assertEqual('456', self.parsed_args.project_id)
 
     def test_deliver_no_msg(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_deliver_command(self.set_parsed_args)
         self.assertEqual(['deliver'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['deliver', '-p', 'someproject', '--user', 'joe123'])
@@ -57,7 +57,7 @@ class TestCommandParser(TestCase):
         self.assertEqual(None, self.parsed_args.project_id)
 
     def test_deliver_with_msg(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_deliver_command(self.set_parsed_args)
         self.assertEqual(['deliver'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['deliver', '-i', '123', '--user', 'joe123', '--msg-file', 'setup.py'])
@@ -66,7 +66,7 @@ class TestCommandParser(TestCase):
         self.assertEqual('123', self.parsed_args.project_id)
 
     def test_share_no_msg(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_share_command(self.set_parsed_args)
         self.assertEqual(['share'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['share', '-p', 'someproject2', '--user', 'joe123'])
@@ -75,7 +75,7 @@ class TestCommandParser(TestCase):
         self.assertEqual(None, self.parsed_args.project_id)
 
     def test_share_with_msg(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_share_command(self.set_parsed_args)
         self.assertEqual(['share'], list(command_parser.subparsers.choices.keys()))
         command_parser.run_command(['share', '-i', '456', '--user', 'joe123', '--msg-file', 'setup.py'])
@@ -85,7 +85,7 @@ class TestCommandParser(TestCase):
 
     def test_list_command(self):
         func = Mock()
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_list_command(func)
         self.assertEqual(['list'], list(command_parser.subparsers.choices.keys()))
 
@@ -113,7 +113,7 @@ class TestCommandParser(TestCase):
         self.assertEqual(args[0].project_name, None)
 
     def test_list_command_long(self):
-        command_parser = CommandParser()
+        command_parser = CommandParser(version_str='1.0')
         command_parser.register_list_command(self.set_parsed_args)
         command_parser.run_command(['list'])
         self.assertEqual(False, self.parsed_args.long_format)
@@ -144,3 +144,8 @@ class TestCommandParser(TestCase):
         self.assertEqual(True, self.parsed_args.long_format)
         self.assertEqual('mouse', self.parsed_args.project_name)
         self.assertEqual(None, self.parsed_args.project_id)
+
+    def test_description(self):
+        expected_description = 'DukeDSClient (1.0) Manage projects/folders/files in the duke-data-service'
+        command_parser = CommandParser(version_str='1.0')
+        self.assertEqual(expected_description, command_parser.parser.description)