Repository: conan-io/conan

Issue:
Py3: Commands with subarguments do and say nothing if no params are entered
Run: `conan editable`,  `conan config`, `conan remote`, `conan profile`, `conan workspace`...
In general all the commands with sub arguments. They should show the help.



Discussion:
```bash
$conan editable

usage: conan editable [-h] {add,remove,list} ...
conan editable: error: too few arguments
ERROR: Exiting with code: 2

$ conan config

usage: conan config [-h] {rm,set,get,install} ...
conan config: error: too few arguments
ERROR: Exiting with code: 2
```

They show the help they have with their subcomands, I don't understand very well this issue.
```
(conan_use) luism@luism-MacBookPro:~/workspace/conan$ conan editable
(conan_use) luism@luism-MacBookPro:~/workspace/conan$ conan workspace
(conan_use) luism@luism-MacBookPro:~/workspace/conan$ 
``` 
For info: I am running Windows, both from source and from ``pip install`` package works the same.
Ok, the difference is py3. In py2 it is working fine.
Edited title
Hi! 
I reproduced this Issue and seems like this is what's happening: [https://bugs.python.org/issue9253#msg186387](https://bugs.python.org/issue9253#msg186387) so setting `subparsers.required = True` makes it work the same in both Py2 and Py3:
```python
    def editable(self, *args):
        """ Manage editable packages
        """
        parser = argparse.ArgumentParser(description=self.editable.__doc__,
                                         prog="conan editable")
        subparsers = parser.add_subparsers(dest='subcommand', help='sub-command help')
        subparsers.required = True
```
I hope this helps!
Thanks so much!

Resolving patch:
diff --git a/conans/client/command.py b/conans/client/command.py
--- a/conans/client/command.py
+++ b/conans/client/command.py
@@ -430,6 +430,8 @@ def config(self, *args):
         parser = argparse.ArgumentParser(description=self.config.__doc__, prog="conan config")
 
         subparsers = parser.add_subparsers(dest='subcommand', help='sub-command help')
+        subparsers.required = True
+
         rm_subparser = subparsers.add_parser('rm', help='Remove an existing config element')
         set_subparser = subparsers.add_parser('set', help='Set a value for a configuration item')
         get_subparser = subparsers.add_parser('get', help='Get the value of configuration item')
@@ -1203,6 +1205,7 @@ def remote(self, *args):
         """
         parser = argparse.ArgumentParser(description=self.remote.__doc__, prog="conan remote")
         subparsers = parser.add_subparsers(dest='subcommand', help='sub-command help')
+        subparsers.required = True
 
         # create the parser for the "a" command
         parser_list = subparsers.add_parser('list', help='List current remotes')
@@ -1318,6 +1321,7 @@ def profile(self, *args):
         """
         parser = argparse.ArgumentParser(description=self.profile.__doc__, prog="conan profile")
         subparsers = parser.add_subparsers(dest='subcommand')
+        subparsers.required = True
 
         # create the parser for the "profile" command
         subparsers.add_parser('list', help='List current profiles')
@@ -1442,6 +1446,7 @@ def workspace(self, *args):
         parser = argparse.ArgumentParser(description=self.workspace.__doc__,
                                          prog="conan workspace")
         subparsers = parser.add_subparsers(dest='subcommand', help='sub-command help')
+        subparsers.required = True
 
         install_parser = subparsers.add_parser('install',
                                                help='same as a "conan install" command'
@@ -1466,6 +1471,7 @@ def editable(self, *args):
         parser = argparse.ArgumentParser(description=self.editable.__doc__,
                                          prog="conan editable")
         subparsers = parser.add_subparsers(dest='subcommand', help='sub-command help')
+        subparsers.required = True
 
         add_parser = subparsers.add_parser('add', help='Put a package in editable mode')
         add_parser.add_argument('path', help='Path to the package folder in the user workspace')


Test patch:
diff --git a/conans/test/functional/command/config_test.py b/conans/test/functional/command/config_test.py
--- a/conans/test/functional/command/config_test.py
+++ b/conans/test/functional/command/config_test.py
@@ -84,3 +84,7 @@ def remove_envvar_test(self):
         self.client.run('config rm env.MY_VAR')
         conf_file = load(self.client.cache.conan_conf_path)
         self.assertNotIn('MY_VAR', conf_file)
+
+    def missing_subarguments_test(self):
+        self.client.run("config", assert_error=True)
+        self.assertIn("ERROR: Exiting with code: 2", self.client.out)
diff --git a/conans/test/functional/command/profile_test.py b/conans/test/functional/command/profile_test.py
--- a/conans/test/functional/command/profile_test.py
+++ b/conans/test/functional/command/profile_test.py
@@ -216,3 +216,8 @@ def profile_force_new_test(self):
         self.assertNotIn("\nos=FakeOS", load(pr_path))
         self.assertNotIn("[env]\nMyEnv=MYVALUe", load(pr_path))
         self.assertEqual(load(pr_path), detected_profile)
+
+    def missing_subarguments_test(self):
+        client = TestClient()
+        client.run("profile", assert_error=True)
+        self.assertIn("ERROR: Exiting with code: 2", client.out)
diff --git a/conans/test/functional/command/remote_test.py b/conans/test/functional/command/remote_test.py
--- a/conans/test/functional/command/remote_test.py
+++ b/conans/test/functional/command/remote_test.py
@@ -364,3 +364,7 @@ def package_refs_test(self):
         self.client.run("remote list_pref Hello1/0.1@user/testing")
         self.assertIn("Hello1/0.1@user/testing:555: remote2", self.client.user_io.out)
         self.assertIn("Hello1/0.1@user/testing:666: remote1", self.client.user_io.out)
+
+    def missing_subarguments_test(self):
+        self.client.run("remote", assert_error=True)
+        self.assertIn("ERROR: Exiting with code: 2", self.client.out)
diff --git a/conans/test/functional/editable/editable_add_test.py b/conans/test/functional/editable/editable_add_test.py
--- a/conans/test/functional/editable/editable_add_test.py
+++ b/conans/test/functional/editable/editable_add_test.py
@@ -63,3 +63,8 @@ class Pck(ConanFile):
         t.run('editable add . wrong/version@user/channel', assert_error=True)
         self.assertIn("ERROR: Name and version from reference (wrong/version@user/channel) and "
                       "target conanfile.py (lib/version) must match", t.out)
+
+    def missing_subarguments_test(self):
+        t = TestClient()
+        t.run("editable", assert_error=True)
+        self.assertIn("ERROR: Exiting with code: 2", t.out)
diff --git a/conans/test/functional/workspace/workspace_test.py b/conans/test/functional/workspace/workspace_test.py
--- a/conans/test/functional/workspace/workspace_test.py
+++ b/conans/test/functional/workspace/workspace_test.py
@@ -976,3 +976,8 @@ class Lib(ConanFile):
         client.run('workspace install "{}"'.format(no_default_file), assert_error=True)
         trial_path = os.path.join(no_default_file, Workspace.default_filename)
         self.assertIn("ERROR: Couldn't load workspace file in {}".format(trial_path), client.out)
+
+    def missing_subarguments_test(self):
+        client = TestClient()
+        client.run("workspace", assert_error=True)
+        self.assertIn("ERROR: Exiting with code: 2", client.out)