Repository: microsoft/ptvsd

Issue:
Changes in CLI arguments between versions
## Environment data

- PTVSD version: 4.1.3
- Using VS Code or Visual Studio: N/A

## Actual behavior

* CLI args for starting apps for remote debugging has changed 
* Now the arg requires `--server-host`, this wasn't the case in the past.
* This is a breaking change.

## Expected  behavior

* We need to revert if possible as existing users will not be able to use PTSVD for remote debugging scenarios.

Reported here https://github.com/Microsoft/vscode-python/issues/2833#issuecomment-428422616



Discussion:
Please feel free to change the Priority label.
FWIW I think the `--server-host` came in on the previous version? I could not get remote debugging working with 2018.8.0 / 4.1.2, and specifically waited for these combination of versions to work again, so please don't just revert if you can manage it.
> so please don't just revert if you can manage it.

No decision had been made yet.

Sorry, I realised that, just providing a bit of extra context. I'm super excited to have remote debugging for django in docker!

Resolving patch:
diff --git a/ptvsd/__main__.py b/ptvsd/__main__.py
--- a/ptvsd/__main__.py
+++ b/ptvsd/__main__.py
@@ -25,8 +25,6 @@
 
 PYDEVD_OPTS = {
     '--file',
-    '--client',
-    #'--port',
     '--vm_type',
 }
 
@@ -99,9 +97,7 @@ def _group_args(argv):
         if gottarget:
             script = argv[i:] + script
             break
-        if arg == '--client':
-            arg = '--host'
-        elif arg == '--file':
+        if arg == '--file':
             if nextarg is None:  # The filename is missing...
                 pydevd.append(arg)
                 continue  # This will get handled later.
@@ -124,14 +120,14 @@ def _group_args(argv):
             supported.append(arg)
 
         # ptvsd support
-        elif arg in ('--host', '--server-host', '--port', '--pid', '-m', '-c', '--subprocess-of', '--subprocess-notify'):
+        elif arg in ('--host', '--port', '--pid', '-m', '-c', '--subprocess-of', '--subprocess-notify'):
             if arg in ('-m', '-c', '--pid'):
                 gottarget = True
             supported.append(arg)
             if nextarg is not None:
                 supported.append(nextarg)
             skip += 1
-        elif arg in ('--single-session', '--wait'):
+        elif arg in ('--single-session', '--wait', '--client'):
             supported.append(arg)
         elif arg == '--multiprocess':
             supported.append(arg)
@@ -152,10 +148,9 @@ def _parse_args(prog, argv):
     parser = argparse.ArgumentParser(prog=prog)
 
     parser.add_argument('--nodebug', action='store_true')
+    parser.add_argument('--client', action='store_true')
 
-    host = parser.add_mutually_exclusive_group()
-    host.add_argument('--host')
-    host.add_argument('--server-host')
+    parser.add_argument('--host', required=True)
     parser.add_argument('--port', type=int, required=True)
 
     def port_range(arg):
@@ -183,17 +178,10 @@ def port_range(arg):
     args = parser.parse_args(argv)
     ns = vars(args)
 
-    serverhost = ns.pop('server_host', None)
-    clienthost = ns.pop('host', None)
-    if serverhost:
-        args.address = Address.as_server(serverhost, ns.pop('port'))
-    elif not clienthost:
-        if args.nodebug:
-            args.address = Address.as_client(clienthost, ns.pop('port'))
-        else:
-            args.address = Address.as_server(clienthost, ns.pop('port'))
-    else:
-        args.address = Address.as_client(clienthost, ns.pop('port'))
+    host = ns.pop('host', None)
+    port = ns.pop('port')
+    client = ns.pop('client')
+    args.address = (Address.as_client if client else Address.as_server)(host, port) # noqa
 
     if ns['multiprocess']:
         options.multiprocess = True
diff --git a/ptvsd/multiproc.py b/ptvsd/multiproc.py
--- a/ptvsd/multiproc.py
+++ b/ptvsd/multiproc.py
@@ -242,7 +242,7 @@ def patch_args(args):
     # itself can remain as is, because ptvsd is compatible with Python in that respect.
     args[i:i] = [
         '-m', 'ptvsd',
-        '--server-host', 'localhost',
+        '--host', 'localhost',
         '--port', '0',
         '--wait',
         '--multiprocess',
diff --git a/pytests/helpers/session.py b/pytests/helpers/session.py
--- a/pytests/helpers/session.py
+++ b/pytests/helpers/session.py
@@ -133,10 +133,11 @@ def prepare_to_run(self, perform_handshake=True, filename=None, module=None, cod
             argv += ['-m', 'ptvsd']
 
         if self.method == 'attach_socket':
-            argv += ['--port', str(self.ptvsd_port), '--wait']
+            argv += ['--wait']
         else:
             self._listen()
-            argv += ['--host', 'localhost', '--port', str(self.ptvsd_port)]
+            argv += ['--client']
+        argv += ['--host', 'localhost', '--port', str(self.ptvsd_port)]
 
         if self.multiprocess:
             argv += ['--multiprocess']


Test patch:
diff --git a/tests/helpers/debugadapter.py b/tests/helpers/debugadapter.py
--- a/tests/helpers/debugadapter.py
+++ b/tests/helpers/debugadapter.py
@@ -235,20 +235,19 @@ def _start(cls, new_proc, argv, addr=None, **kwargs):
     def _ensure_addr(cls, argv, addr):
         if '--host' in argv:
             raise ValueError("unexpected '--host' in argv")
-        if '--server-host' in argv:
-            raise ValueError("unexpected '--server-host' in argv")
         if '--port' in argv:
             raise ValueError("unexpected '--port' in argv")
+        if '--client' in argv:
+            raise ValueError("unexpected '--client' in argv")
         host, port = addr
 
         argv.insert(0, str(port))
         argv.insert(0, '--port')
 
         argv.insert(0, host)
-        if addr.isserver:
-            argv.insert(0, '--server-host')
-        else:
-            argv.insert(0, '--host')
+        argv.insert(0, '--host')
+        if not addr.isserver:
+            argv.insert(0, '--client')
 
     def __init__(self, proc, addr, owned=False):
         super(DebugAdapter, self).__init__()
diff --git a/tests/ptvsd/test___main__.py b/tests/ptvsd/test___main__.py
--- a/tests/ptvsd/test___main__.py
+++ b/tests/ptvsd/test___main__.py
@@ -9,28 +9,18 @@ class ParseArgsTests(unittest.TestCase):
 
     EXPECTED_EXTRA = ['--']
 
-    def test_module(self):
-        args, extra = parse_args([
-            'eggs',
-            '--port', '8888',
-            '-m', 'spam',
-        ])
-
-        self.assertEqual(vars(args), {
-            'kind': 'module',
-            'name': 'spam',
-            'address': Address.as_server(None, 8888),
-            'nodebug': False,
-            'single_session': False,
-            'wait': False,
-            'multiprocess': False,
-        })
-        self.assertEqual(extra, self.EXPECTED_EXTRA)
+    def test_host_required(self):
+        with self.assertRaises(SystemExit):
+            parse_args([
+                'eggs',
+                '--port', '8888',
+                '-m', 'spam',
+            ])
 
     def test_module_server(self):
         args, extra = parse_args([
             'eggs',
-            '--server-host', '10.0.1.1',
+            '--host', '10.0.1.1',
             '--port', '8888',
             '-m', 'spam',
         ])
@@ -50,6 +40,8 @@ def test_module_nodebug(self):
         args, extra = parse_args([
             'eggs',
             '--nodebug',
+            '--client',
+            '--host', 'localhost',
             '--port', '8888',
             '-m', 'spam',
         ])
@@ -57,7 +49,7 @@ def test_module_nodebug(self):
         self.assertEqual(vars(args), {
             'kind': 'module',
             'name': 'spam',
-            'address': Address.as_client(None, 8888),
+            'address': Address.as_client('localhost', 8888),
             'nodebug': True,
             'single_session': False,
             'wait': False,
@@ -68,6 +60,7 @@ def test_module_nodebug(self):
     def test_script(self):
         args, extra = parse_args([
             'eggs',
+            '--host', 'localhost',
             '--port', '8888',
             'spam.py',
         ])
@@ -75,7 +68,7 @@ def test_script(self):
         self.assertEqual(vars(args), {
             'kind': 'script',
             'name': 'spam.py',
-            'address': Address.as_server(None, 8888),
+            'address': Address.as_server('localhost', 8888),
             'nodebug': False,
             'single_session': False,
             'wait': False,
@@ -86,7 +79,7 @@ def test_script(self):
     def test_script_server(self):
         args, extra = parse_args([
             'eggs',
-            '--server-host', '10.0.1.1',
+            '--host', '10.0.1.1',
             '--port', '8888',
             'spam.py',
         ])
@@ -106,6 +99,8 @@ def test_script_nodebug(self):
         args, extra = parse_args([
             'eggs',
             '--nodebug',
+            '--client',
+            '--host', 'localhost',
             '--port', '8888',
             'spam.py',
         ])
@@ -113,7 +108,7 @@ def test_script_nodebug(self):
         self.assertEqual(vars(args), {
             'kind': 'script',
             'name': 'spam.py',
-            'address': Address.as_client(None, 8888),
+            'address': Address.as_client('localhost', 8888),
             'nodebug': True,
             'single_session': False,
             'wait': False,
@@ -124,6 +119,7 @@ def test_script_nodebug(self):
     def test_remote(self):
         args, extra = parse_args([
             'eggs',
+            '--client',
             '--host', '1.2.3.4',
             '--port', '8888',
             'spam.py',
@@ -143,6 +139,7 @@ def test_remote(self):
     def test_remote_localhost(self):
         args, extra = parse_args([
             'eggs',
+            '--client',
             '--host', 'localhost',
             '--port', '8888',
             'spam.py',
@@ -163,6 +160,7 @@ def test_remote_nodebug(self):
         args, extra = parse_args([
             'eggs',
             '--nodebug',
+            '--client',
             '--host', '1.2.3.4',
             '--port', '8888',
             'spam.py',
@@ -183,6 +181,7 @@ def test_remote_single_session(self):
         args, extra = parse_args([
             'eggs',
             '--single-session',
+            '--host', 'localhost',
             '--port', '8888',
             'spam.py',
         ])
@@ -202,7 +201,7 @@ def test_local_single_session(self):
         args, extra = parse_args([
             'eggs',
             '--single-session',
-            '--server-host', '1.2.3.4',
+            '--host', '1.2.3.4',
             '--port', '8888',
             'spam.py',
         ])
@@ -221,6 +220,7 @@ def test_local_single_session(self):
     def test_remote_wait(self):
         args, extra = parse_args([
             'eggs',
+            '--client',
             '--host', '1.2.3.4',
             '--port', '8888',
             '--wait',
@@ -242,6 +242,7 @@ def test_extra(self):
         args, extra = parse_args([
             'eggs',
             '--DEBUG',
+            '--host', 'localhost',
             '--port', '8888',
             '--vm_type', '???',
             'spam.py',
@@ -257,7 +258,7 @@ def test_extra(self):
         self.assertEqual(vars(args), {
             'kind': 'script',
             'name': 'spam.py',
-            'address': Address.as_server(None, 8888),
+            'address': Address.as_server('localhost', 8888),
             'nodebug': False,
             'single_session': False,
             'wait': False,
@@ -280,6 +281,8 @@ def test_extra_nodebug(self):
             'eggs',
             '--DEBUG',
             '--nodebug',
+            '--client',
+            '--host', 'localhost',
             '--port', '8888',
             '--vm_type', '???',
             'spam.py',
@@ -295,7 +298,7 @@ def test_extra_nodebug(self):
         self.assertEqual(vars(args), {
             'kind': 'script',
             'name': 'spam.py',
-            'address': Address.as_client(None, 8888),
+            'address': Address.as_client('localhost', 8888),
             'nodebug': True,
             'single_session': False,
             'wait': False,
@@ -342,124 +345,10 @@ def test_unsupported_arg(self):
                     'spam.py',
                 ])
 
-    def test_backward_compatibility_host(self):
-        args, extra = parse_args([
-            'eggs',
-            '--client', '1.2.3.4',
-            '--port', '8888',
-            '-m', 'spam',
-        ])
-
-        self.assertEqual(vars(args), {
-            'kind': 'module',
-            'name': 'spam',
-            'address': Address.as_client('1.2.3.4', 8888),
-            'nodebug': False,
-            'single_session': False,
-            'wait': False,
-            'multiprocess': False,
-        })
-        self.assertEqual(extra, self.EXPECTED_EXTRA)
-
-    def test_backward_compatibility_host_nodebug(self):
-        args, extra = parse_args([
-            'eggs',
-            '--nodebug',
-            '--client', '1.2.3.4',
-            '--port', '8888',
-            '-m', 'spam',
-        ])
-
-        self.assertEqual(vars(args), {
-            'kind': 'module',
-            'name': 'spam',
-            'address': Address.as_client('1.2.3.4', 8888),
-            'nodebug': True,
-            'single_session': False,
-            'wait': False,
-            'multiprocess': False,
-        })
-        self.assertEqual(extra, self.EXPECTED_EXTRA)
-
-    def test_backward_compatibility_module(self):
-        args, extra = parse_args([
-            'eggs',
-            '--port', '8888',
-            '--module',
-            '--file', 'spam:',
-        ])
-
-        self.assertEqual(vars(args), {
-            'kind': 'module',
-            'name': 'spam',
-            'address': Address.as_server(None, 8888),
-            'nodebug': False,
-            'single_session': False,
-            'wait': False,
-            'multiprocess': False,
-        })
-        self.assertEqual(extra, self.EXPECTED_EXTRA)
-
-    def test_backward_compatibility_module_nodebug(self):
-        args, extra = parse_args([
-            'eggs',
-            '--nodebug',
-            '--port', '8888',
-            '--module',
-            '--file', 'spam:',
-        ])
-
-        self.assertEqual(vars(args), {
-            'kind': 'module',
-            'name': 'spam',
-            'address': Address.as_client(None, 8888),
-            'nodebug': True,
-            'single_session': False,
-            'wait': False,
-            'multiprocess': False,
-        })
-        self.assertEqual(extra, self.EXPECTED_EXTRA)
-
-    def test_backward_compatibility_script(self):
-        args, extra = parse_args([
-            'eggs',
-            '--port', '8888',
-            '--file', 'spam.py',
-        ])
-
-        self.assertEqual(vars(args), {
-            'kind': 'script',
-            'name': 'spam.py',
-            'address': Address.as_server(None, 8888),
-            'nodebug': False,
-            'single_session': False,
-            'wait': False,
-            'multiprocess': False,
-        })
-        self.assertEqual(extra, self.EXPECTED_EXTRA)
-
-    def test_backward_compatibility_script_nodebug(self):
-        args, extra = parse_args([
-            'eggs',
-            '--nodebug',
-            '--port', '8888',
-            '--file', 'spam.py',
-        ])
-
-        self.assertEqual(vars(args), {
-            'kind': 'script',
-            'name': 'spam.py',
-            'address': Address.as_client(None, 8888),
-            'nodebug': True,
-            'single_session': False,
-            'wait': False,
-            'multiprocess': False,
-        })
-        self.assertEqual(extra, self.EXPECTED_EXTRA)
-
     def test_pseudo_backward_compatibility(self):
         args, extra = parse_args([
             'eggs',
+            '--host', 'localhost',
             '--port', '8888',
             '--module',
             '--file', 'spam',
@@ -468,7 +357,7 @@ def test_pseudo_backward_compatibility(self):
         self.assertEqual(vars(args), {
             'kind': 'script',
             'name': 'spam',
-            'address': Address.as_server(None, 8888),
+            'address': Address.as_server('localhost', 8888),
             'nodebug': False,
             'single_session': False,
             'wait': False,
@@ -480,6 +369,8 @@ def test_pseudo_backward_compatibility_nodebug(self):
         args, extra = parse_args([
             'eggs',
             '--nodebug',
+            '--client',
+            '--host', 'localhost',
             '--port', '8888',
             '--module',
             '--file', 'spam',
@@ -488,7 +379,7 @@ def test_pseudo_backward_compatibility_nodebug(self):
         self.assertEqual(vars(args), {
             'kind': 'script',
             'name': 'spam',
-            'address': Address.as_client(None, 8888),
+            'address': Address.as_client('localhost', 8888),
             'nodebug': True,
             'single_session': False,
             'wait': False,
diff --git a/tests/system_tests/test_connection.py b/tests/system_tests/test_connection.py
--- a/tests/system_tests/test_connection.py
+++ b/tests/system_tests/test_connection.py
@@ -115,6 +115,7 @@ def connect(addr, wait=None, closeonly=False):
         proc = Proc.start_python_module('ptvsd', [
             '--server',
             '--wait',
+            '--host', 'localhost',
             '--port', '5678',
             '--file', filename,
         ], env={