internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: iterative/dvc

Issue:
`--with-deps` and `pipeline show` don't see a dummy stage
```
│#!/bin/bash
│
│set -e
│set -x
│
│rm -rf myrepo
│mkdir myrepo
│cd myrepo
│git init
│dvc init
│
│mkdir foo
│echo foo/
│echo 1 > foo/1
│dvc add foo/1
│echo 2 > foo/2
│dvc add foo/2
│dvc run -d foo/1 -d foo/2 -f Dvcfile
│dvc run -d foo -o bar 'echo bar > bar'
│
│dvc unprotect foo/1
│echo 3 > foo/1
│
│dvc repro bar.dvc
│dvc pipeline show bar.dvc
```

produces

```
...
 dvc repro bar.dvc
Dependency 'foo' of 'bar.dvc' changed.
Stage 'bar.dvc' changed.
Reproducing 'bar.dvc'
Running command:
        echo bar > bar
Output 'bar' didn't change. Skipping saving.
Saving information to 'bar.dvc'.

To track the changes with git run:

        git add bar.dvc
+ dvc pipeline show bar.dvc
bar.dvc
```


Discussion:

Resolving patch:
diff --git a/dvc/project.py b/dvc/project.py
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -1058,7 +1058,8 @@ def graph(self):
             for dep in stage.deps:
                 for out in outs:
                     if out.path != dep.path \
-                       and not dep.path.startswith(out.path + out.sep):
+                       and not dep.path.startswith(out.path + out.sep) \
+                       and not out.path.startswith(dep.path + dep.sep):
                         continue
 
                     dep_stage = out.stage


Test patch:
diff --git a/tests/test_repro.py b/tests/test_repro.py
--- a/tests/test_repro.py
+++ b/tests/test_repro.py
@@ -79,6 +79,47 @@ def test(self):
         self.assertTrue(filecmp.cmp(self.file1, self.FOO, shallow=False))
 
 
+class TestReproDepDirWithOutputsUnderIt(TestDvc):
+    def test(self):
+        stages = self.dvc.add(self.DATA)
+        self.assertEqual(len(stages), 1)
+        self.assertTrue(stages[0] is not None)
+
+        sleep()
+
+        stages = self.dvc.add(self.DATA_SUB)
+        self.assertEqual(len(stages), 1)
+        self.assertTrue(stages[0] is not None)
+
+        sleep()
+
+        stage = self.dvc.run(fname='Dvcfile',
+                             deps=[self.DATA, self.DATA_SUB])
+        self.assertTrue(stage is not None)
+
+        sleep()
+
+        file1 = 'file1'
+        file1_stage = file1 + '.dvc'
+        stage = self.dvc.run(fname=file1_stage,
+                             deps=[self.DATA_DIR],
+                             outs=[file1],
+                             cmd='python {} {} {}'.format(self.CODE,
+                                                          self.DATA,
+                                                          file1))
+        self.assertTrue(stage is not None)
+
+        sleep()
+
+        os.unlink(self.DATA)
+        shutil.copyfile(self.FOO, self.DATA)
+
+        sleep()
+
+        stages = self.dvc.reproduce(file1_stage)
+        self.assertEqual(len(stages), 2)
+
+
 class TestReproNoDeps(TestRepro):
     def test(self):
         out = 'out'
Repository: iterative/dvc

Issue:
Error: Failed to run command: Stage file 'Dvcfile' format error: None should be instance of 'dict'
```
echo '' > Dvcfile
dvc run -o foo  -f Dvcfile touch foo
```

```
Error: Traceback (most recent call last):
  File "/home/efiop/.virtualenvs/dvc/lib/python2.7/site-packages/dvc/command/run.py", line 18, in run
    no_exec=self.args.no_exec)
  File "/home/efiop/.virtualenvs/dvc/lib/python2.7/site-packages/dvc/project.py", line 319, in run
    self._check_output_duplication(stage.outs)
  File "/home/efiop/.virtualenvs/dvc/lib/python2.7/site-packages/dvc/project.py", line 155, in _check_out
put_duplication
    for stage in self.stages():
  File "/home/efiop/.virtualenvs/dvc/lib/python2.7/site-packages/dvc/project.py", line 1106, in stages
    stage = Stage.load(self, path)
  File "/home/efiop/.virtualenvs/dvc/lib/python2.7/site-packages/dvc/stage.py", line 366, in load
    return Stage.loadd(project, yaml.safe_load(fd), fname)
  File "/home/efiop/.virtualenvs/dvc/lib/python2.7/site-packages/dvc/stage.py", line 243, in loadd
    Stage.validate(d, fname=os.path.relpath(path))
  File "/home/efiop/.virtualenvs/dvc/lib/python2.7/site-packages/dvc/stage.py", line 239, in validate
    raise StageFileFormatError(fname, exc)
StageFileFormatError: Stage file 'Dvcfile' format error: None should be instance of 'dict'

Error: Failed to run command: Stage file 'Dvcfile' format error: None should be instance of 'dict'

Having any troubles? Hit us up at dvc.org/support, we are always happy to help!

```


Discussion:

Resolving patch:
diff --git a/dvc/stage.py b/dvc/stage.py
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -363,7 +363,7 @@ def load(project, fname):
             raise StageFileIsNotDvcFileError(fname)
 
         with open(fname, 'r') as fd:
-            return Stage.loadd(project, yaml.safe_load(fd), fname)
+            return Stage.loadd(project, yaml.safe_load(fd) or dict(), fname)
 
     def dumpd(self):
         deps = [x.dumpd() for x in self.deps]


Test patch:
Repository: iterative/dvc

Issue:
import: Set output as an optional value, defaulting to the name of the file.
e.g. `dvc import s3://gdelt-open-data/events/20181114.export.csv` would set the output name to `20181114.export.csv`


Discussion:

Resolving patch:
diff --git a/dvc/cli.py b/dvc/cli.py
--- a/dvc/cli.py
+++ b/dvc/cli.py
@@ -176,6 +176,7 @@ def parse_args(argv=None):
                              "`dvc remote` commands). ")
     import_parser.add_argument(
                         'out',
+                        nargs='?',
                         help='Output.')
     import_parser.set_defaults(func=CmdImport)
 
diff --git a/dvc/command/imp.py b/dvc/command/imp.py
--- a/dvc/command/imp.py
+++ b/dvc/command/imp.py
@@ -1,3 +1,10 @@
+import os
+
+try:
+    from urlparse import urlparse
+except ImportError:
+    from urllib.parse import urlparse
+
 from dvc.exceptions import DvcException
 from dvc.command.base import CmdBase
 from dvc.logger import Logger
@@ -6,7 +13,13 @@
 class CmdImport(CmdBase):
     def run(self):
         try:
-            self.project.imp(self.args.url, self.args.out)
+            default_out = os.path.basename(
+                urlparse(self.args.url).path
+            )
+
+            out = self.args.out or default_out
+
+            self.project.imp(self.args.url, out)
         except DvcException as ex:
             Logger.error('Failed to import {}'.format(self.args.url), ex)
             return 1


Test patch:
diff --git a/tests/test_import.py b/tests/test_import.py
--- a/tests/test_import.py
+++ b/tests/test_import.py
@@ -1,6 +1,8 @@
 import os
 import stat
 import shutil
+import tempfile
+from uuid import uuid4
 
 from dvc.main import main
 from dvc.command.imp import CmdImport
@@ -11,14 +13,27 @@
 
 class TestCmdImport(TestDvc):
     def test(self):
-        ret = main(['import',
-                    self.FOO, 'import'])
+        ret = main(['import', self.FOO, 'import'])
         self.assertEqual(ret, 0)
+        self.assertTrue(os.path.exists('import.dvc'))
 
-        ret = main(['import',
-                    'non-existing-file', 'import'])
+        ret = main(['import', 'non-existing-file', 'import'])
         self.assertNotEqual(ret, 0)
 
     def test_unsupported(self):
         ret = main(['import', 'unsupported://path', 'import_unsupported'])
         self.assertNotEqual(ret, 0)
+
+class TestDefaultOutput(TestDvc):
+    def test(self):
+        tmpdir = self.mkdtemp()
+        filename = str(uuid4())
+        tmpfile = os.path.join(tmpdir, filename)
+
+        with open(tmpfile, 'w') as fd:
+            fd.write('content')
+
+        ret = main(['import', tmpfile])
+        self.assertEqual(ret, 0)
+        self.assertTrue(os.path.exists(filename))
+        self.assertEqual(open(filename).read(), 'content')
Repository: iterative/dvc

Issue:
metrics add: don't require file to exist
```
$ dvc run -O foo --no-exec 'echo foo > foo'
$ dvc metrics add foo
Error: Unexpected error: [Errno 2] No such file or directory: '/storage/git/dvc/myrepo/foo'
```


Discussion:

Resolving patch:
diff --git a/dvc/output/local.py b/dvc/output/local.py
--- a/dvc/output/local.py
+++ b/dvc/output/local.py
@@ -72,6 +72,9 @@ def _verify_metric(self):
         if not self.metric:
             return
 
+        if not os.path.exists(self.path):
+            return
+
         if os.path.isdir(self.path):
             msg = 'Directory \'{}\' cannot be used as metrics.'
             raise DvcException(msg.format(self.rel_path))


Test patch:
Repository: iterative/dvc

Issue:
init: mention that we have chat



Discussion:
Let's also put something like `what's next` - check get started, `dvc add` to start tracking models or data sets, `dvc run` to create your first stage
@shcheklein , what do you think about this?

![2018-11-19-22 22 21](https://user-images.githubusercontent.com/7363250/48751387-bf3cca00-ec49-11e8-9185-49d547ecc42a.png)

Is it too cheesy :cheese: ? 
Looks great, @mroutis !

I would simplify it a little bit. Remove `Start tracking ....` - it does not provide much value and covers only a specific niche - models. I would also change the chat copy:

`Join our community chat to get help and share ideas`
Indeed, @shcheklein , I wasn't sure about that green part either:

![2018-11-19-22 31 24](https://user-images.githubusercontent.com/7363250/48751624-037c9a00-ec4b-11e8-8c31-f13840bfa4d0.png)

Final cut?

Resolving patch:
diff --git a/dvc/project.py b/dvc/project.py
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -78,6 +78,7 @@ def init(root_dir=os.curdir, no_scm=False, force=False):
         Raises:
             KeyError: Raises an exception.
         """
+        import colorama
         import shutil
         from dvc.scm import SCM, Base
         from dvc.config import Config
@@ -105,7 +106,21 @@ def init(root_dir=os.curdir, no_scm=False, force=False):
         if scm.ignore_file():
             scm.add([os.path.join(dvc_dir, scm.ignore_file())])
 
-        Logger.info('You can now commit the changes to git.')
+        Logger.info('\nYou can now commit the changes to git.')
+
+        Logger.info(
+            "\n"
+            "{yellow}What's next?{nc}\n"
+            "{yellow}------------{nc}\n"
+            "- Check out the documentation: {blue}https://dvc.org/doc{nc}\n"
+            "- Get help and share ideas: {blue}https://dvc.org/chat{nc}\n"
+            "- Star us on GitHub: {blue}https://github.com/iterative/dvc{nc}"
+
+            .format(yellow=colorama.Fore.YELLOW,
+                    blue=colorama.Fore.BLUE,
+                    green=colorama.Fore.GREEN,
+                    nc=colorama.Fore.RESET)
+        )
 
         return proj
 


Test patch:
Repository: iterative/dvc

Issue:
pipeline show --ascii: `An operation was attempted on something that is not a socket`
From https://gist.github.com/artichaud1/e61905d826bc2bdbaaf7f3e05e812501 

```
λ dvc pipeline show --ascii -v
Error: Traceback (most recent call last):
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\main.py", line 22, in main
    ret = cmd.run_cmd()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\command\base.py", line 41, in run_cmd
    return self.run()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\command\pipeline.py", line 98, in run
    self.args.outs)
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\command\pipeline.py", line 79, in _show_ascii
    d.draw()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\dagascii.py", line 278, in draw
    canvas.draw()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\dagascii.py", line 23, in draw
    Screen.wrapper(self._do_draw)
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\asciimatics\screen.py", line 1170, in wrapper
    return func(screen)
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\dagascii.py", line 67, in _do_draw
    select.select([sys.stdin], [], [], None)
OSError: [WinError 10038] An operation was attempted on something that is not a socket

Error: Unexpected error: [WinError 10038] An operation was attempted on something that is not a socket
```


Discussion:

Resolving patch:
diff --git a/dvc/dagascii.py b/dvc/dagascii.py
--- a/dvc/dagascii.py
+++ b/dvc/dagascii.py
@@ -1,6 +1,5 @@
 import sys
 import math
-import select
 
 from grandalf.graphs import Vertex, Edge, Graph
 from grandalf.layouts import SugiyamaLayout
@@ -8,6 +7,8 @@
 
 
 class AsciiCanvas(object):
+    TIMEOUT = 1
+
     def __init__(self, cols, lines):
         assert cols > 1
         assert lines > 1
@@ -64,7 +65,13 @@ def _do_draw(self, screen):  # pragma: no cover
 
             # NOTE: get_event() doesn't block by itself,
             # so we have to do the blocking ourselves.
-            select.select([sys.stdin], [], [], None)
+            #
+            # NOTE: using formally private method while waiting for PR [1]
+            # to get merged. After that need to adjust asciimatics version
+            # requirements.
+            #
+            # [1] https://github.com/peterbrittain/asciimatics/pull/188
+            screen._wait_for_input(self.TIMEOUT)
 
             event = screen.get_event()
             if not isinstance(event, KeyboardEvent):
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@
     "jsonpath-rw==1.4.0",
     "requests>=2.18.4",
     "grandalf==0.6",
-    "asciimatics>=1.10.0",
+    "asciimatics==1.10.0",
     "distro>=1.3.0",
 ]
 


Test patch:
Repository: iterative/dvc

Issue:
Better status for aggregate DVC files
DVC version : 0.20.0 (python 3.6 anaconda install)

```
#!/bin/bash

# Create repository
rm -rf myrepo
mkdir myrepo
cd myrepo

# Init Git and DVC
git init
dvc init
git commit -s -m"Init"

# Create data directory with ("proccesed" data and "raw" data)
mkdir -p main_data/data/procdata
mkdir -p main_data/data/rawdata

# Create initial rawdata
#
#   echo 1 > main_data/data/rawdata/file1.txt
#   echo 2 > main_data/data/rawdata/file2.txt
#
for d in {1..2}; do
    echo $d > main_data/data/rawdata/file$d.txt
done

# Create two `dvc` files: (file1.txt.dvc && file2.txt.dvc)
#
# - Change directory to `main/data/procdata`
# - Dependency: `main_data/data/rawdata/file1.txt
# - Output:     `main_data/data/procdata/file1.txt
# - Command:    `cp main_data/data/rawdata/file1.txt main_data/data/procdata
for d in {1..2}; do
    dvc run \
      --no-exec \
      -c main_data/data/procdata \
      -d ../rawdata/file$d.txt \
      -o file$d.txt \
      cp ../rawdata/file$d.txt .

    DEPS="$DEPS -d procdata/file$d.txt"
done

echo "Dependency flags: $DEPS"

dvc run \
  --no-exec \
  -c main_data/data \
  $DEPS \
  -f data.dvc

dvc repro main_data/data/data.dvc

# Now modify file1.txt
echo 5 > main_data/data/rawdata/file1.txt
dvc status main_data/data/procdata/file1.txt.dvc
dvc status main_data/data/data.dvc
```

The first `dvc status` command will show that `file1.txt` has been modified. However, the second  `dvc status` command shows that everything is up to date.

This is misleading because calling `dvc repro main_data/data/data.dvc` actually re-runs the whole pipeline to account for the change in `file1.txt`

Is it possible to fix this behaviour of `dvc status` ?


Discussion:

Resolving patch:
diff --git a/dvc/project.py b/dvc/project.py
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -788,11 +788,12 @@ def pull(self,
                    with_deps=with_deps)
         self.checkout(target=target, with_deps=with_deps, force=force)
 
-    def _local_status(self, target=None):
+    def _local_status(self, target=None, with_deps=False):
         status = {}
 
         if target:
-            stages = [Stage.load(self, target)]
+            stages = self._collect(target,
+                                   with_deps=with_deps)
         else:
             stages = self.active_stages()
 
@@ -859,7 +860,8 @@ def status(self,
                                           all_branches=all_branches,
                                           with_deps=with_deps,
                                           all_tags=all_tags)
-            return self._local_status(target)
+            return self._local_status(target,
+                                      with_deps=with_deps)
 
     def _read_metric_json(self, fd, json_path):
         import json


Test patch:
Repository: iterative/dvc

Issue:
run: escape arguments with spaces in it
```
#!/bin/bash

set -e
set -x

rm -rf myrepo
mkdir myrepo
cd myrepo

git init
dvc init

echo 'echo $1' > script.sh
chmod +x script.sh

./script.sh arg1 arg2
./script.sh 'arg1 arg2'

dvc run ./script.sh 'arg1 arg2'
```

`arg1 arg2` are passed as a single argument to dvc, but we join() it in dvc/command/run.py, without escaping it, causing such behavior.


Discussion:

Resolving patch:
diff --git a/dvc/command/run.py b/dvc/command/run.py
--- a/dvc/command/run.py
+++ b/dvc/command/run.py
@@ -3,12 +3,28 @@
 
 
 class CmdRun(CmdBase):
+    def _joined_cmd(self):
+        if len(self.args.command) == 0:
+            return ''
+
+        if len(self.args.command) == 1:
+            return self.args.command[0]
+
+        cmd = ''
+        for chunk in self.args.command:
+            if len(chunk.split()) != 1:
+                fmt = ' "{}"'
+            else:
+                fmt = ' {}'
+            cmd += fmt.format(chunk)
+        return cmd
+
     def run(self):
         try:
             if self.args.yes:
                 self.project.prompt.default = True
 
-            self.project.run(cmd=' '.join(self.args.command),
+            self.project.run(cmd=self._joined_cmd(),
                              outs=self.args.outs,
                              outs_no_cache=self.args.outs_no_cache,
                              metrics_no_cache=self.args.metrics_no_cache,


Test patch:
diff --git a/tests/test_run.py b/tests/test_run.py
--- a/tests/test_run.py
+++ b/tests/test_run.py
@@ -156,3 +156,20 @@ def test_run_bad_command(self):
         ret = main(['run',
                     'non-existing-command'])
         self.assertNotEqual(ret, 0)
+
+    def test_run_args_with_spaces(self):
+        with open(self.CODE, 'w') as fobj:
+            fobj.write("import sys\nopen(sys.argv[1], 'w+').write(sys.argv[2])")
+
+        arg = 'arg1 arg2'
+        log = 'log'
+        ret = main(['run',
+                    'python',
+                    self.CODE,
+                    log,
+                    'arg1 arg2'])
+
+        self.assertEqual(ret, 0)
+
+        with open(log, 'r') as fobj:
+            self.assertEqual(fobj.read(), arg)
Repository: iterative/dvc

Issue:
dvc: don't initialize default remote automatically



Discussion:

Resolving patch:
diff --git a/dvc/data_cloud.py b/dvc/data_cloud.py
--- a/dvc/data_cloud.py
+++ b/dvc/data_cloud.py
@@ -27,18 +27,19 @@ def __init__(self, project, config=None):
         self._config = config
         self._core = self._config[Config.SECTION_CORE]
 
+    @property
+    def _cloud(self):
         remote = self._core.get(Config.SECTION_CORE_REMOTE, '')
-        if remote == '':
-            if self._core.get(Config.SECTION_CORE_CLOUD, None):
-                # backward compatibility
-                msg = 'Using obsoleted config format. Consider updating.'
-                Logger.warn(msg)
-                self._cloud = self.__init__compat()
-            else:
-                self._cloud = None
-            return
+        if remote != '':
+            return self._init_remote(remote)
 
-        self._cloud = self._init_remote(remote)
+        if self._core.get(Config.SECTION_CORE_CLOUD, None):
+            # backward compatibility
+            msg = 'Using obsoleted config format. Consider updating.'
+            Logger.warn(msg)
+            return self._init_compat()
+
+        return None
 
     @staticmethod
     def supported(config):
@@ -60,7 +61,7 @@ def _init_remote(self, remote):
 
         return self._init_cloud(cloud_config, cloud_type)
 
-    def __init__compat(self):
+    def _init_compat(self):
         name = self._core.get(Config.SECTION_CORE_CLOUD, '').strip().lower()
         if name == '':
             self._cloud = None


Test patch:
diff --git a/tests/test_data_cloud.py b/tests/test_data_cloud.py
--- a/tests/test_data_cloud.py
+++ b/tests/test_data_cloud.py
@@ -175,11 +175,15 @@ def test(self):
             self._test_cloud(config, cl)
 
     def test_unsupported(self):
+        remote_url = 'notsupportedscheme://a/b'
+        config = TEST_CONFIG
+        config[TEST_SECTION][Config.SECTION_REMOTE_URL] = remote_url
+
+        # NOTE: making sure that error doesn't raise too early
+        cloud = DataCloud(self.dvc, config=config)
+
         with self.assertRaises(ConfigError):
-            remote_url = 'notsupportedscheme://a/b'
-            config = TEST_CONFIG
-            config[TEST_SECTION][Config.SECTION_REMOTE_URL] = remote_url
-            DataCloud(self.dvc, config=config)
+            cloud._cloud
 
 
 class TestDataCloudBase(TestDvc):
Repository: iterative/dvc

Issue:
no prompt for keyfile passphrase; unhelpful message not a valid OPENSSH private key file
Hi,

I have dvc setup with -
dvc version = 0.22.0
Platform = Ubuntu 16.04.5 LTS
Installation method = pip3 install dvc

I have configured a ssh remote and a passphrase protected keyfile. I have verified that I can ssh into the remote machine with the given keyfile. However, `dvc pull` fails with
> Error: Failed to pull data from the cloud: not a valid OPENSSH private key file
and doesn't prompt me for a passphrase

Could you enable prompt for passphrase for protected keyfiles?


Discussion:
Hi @sunavc !

Have you tried setting `ask_password` option in dvc config?

```
dvc remote modify mysshremote ask_password true
```

Thanks,
Ruslan
Ok. I tried setting the `ask_password true` and it effectively works. The prompt

> Enter password for host [host] port [port] user [user]:

is a bit misleading since the ssh key passphrase should be entered.

Also, adding this example to the documentation at https://github.com/iterative/dvc.org/blob/master/static/docs/commands-reference/remote.md#click-for-ssh-available-options will increase awareness.

Thanks!
Hi @sunavc !

Great point! Edited doc https://github.com/iterative/dvc.org/commit/ee7e7577a2623c8d0f2d6a54b4d3d863cb77d71d to mention that password can be used as a private key passphrase. Will edit password prompt message ASAP too, leaving this issue open until it is done. Thank you for the feedback!

Resolving patch:
diff --git a/dvc/prompt.py b/dvc/prompt.py
--- a/dvc/prompt.py
+++ b/dvc/prompt.py
@@ -32,7 +32,7 @@ def prompt_password(self, msg):  # pragma: no cover
         if not sys.stdout.isatty():
             return None
 
-        msg = 'Enter password for {}:\n'.format(msg)
+        msg = '{}:\n'.format(msg)
 
         if not progress.is_finished:
             msg = u'\n' + msg
diff --git a/dvc/remote/ssh.py b/dvc/remote/ssh.py
--- a/dvc/remote/ssh.py
+++ b/dvc/remote/ssh.py
@@ -91,7 +91,8 @@ def ssh(self, host=None, user=None, port=None):
         ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 
         if self.ask_password and self.password is None:
-            msg = "host '{}' port '{}' user '{}'".format(host, port, user)
+            msg = ("Enter a private key passphrase or a password for "
+                   "host '{}' port '{}' user '{}'").format(host, port, user)
             self.password = self.project.prompt.prompt_password(msg)
 
         ssh.connect(host,


Test patch: