Repository: iterative/dvc
Pull request: get/import: more meaningful message on NoRemoteError
* [x] ❗ Have you followed the guidelines in the [Contributing to DVC](https://dvc.org/doc/user-guide/contributing/core) list?

* [x] 📖 Check this box if this PR **does not** require [documentation](https://dvc.org/doc) updates, or if it does **and** you have created a separate PR in [dvc.org](https://github.com/iterative/dvc.org) with such updates (or at least opened an issue about it in that repo). Please link below to your PR (or issue) in the [dvc.org](https://github.com/iterative/dvc.org) repo.

* [x] ❌ Have you checked DeepSource, CodeClimate, and other sanity checks below? We consider their findings recommendatory and don't expect everything to be addresses. Please review them carefully and fix those that actually improve code or fix bugs.

Thank you for the contribution - we'll try to review it as soon as possible. 🙏

Fixes #2711 

Problem statement:
get/import: improve error message on no default remote
Since we allow importing/getting files that are not cached this error does not make much sense:

```
failed to import 'model.pkl' from '../test-import/'. - config file error: no remote specified. Setup default remote with
```

in a lot of cases.

Hints from issue discussion:
So is this just a wrong error message? 
I would say it's in a wrong place. We need to raise this only when we try to import a cached object and no default remote is specified.
@shcheklein, @Suor  I found out I could not run `dvc import` if the source repo has no default remote set. Also, the error I got (see below) confused me, because it made me think I had to run `dvc config core.remote` in the working repository.

```
ERROR: failed to import 'models/spacy_model/' from 'git@gitlab.com:iomed/datascience/spacy-model-es-cat'. - config file error: no remote specified. Setup default remote with
    dvc config core.remote <name>
or use:
    dvc pull -r <name>
```
As a newbie dvc user who might be missing something, I'd say it would be useful to:

- Skip the error message shown by @shcheklein 
- If no default remotes are set:
    - in the source repository, have a more explicit error message indicating that the problem is in the source repository.
    - Have a parameter to indicate the remote to use, maybe?
+1 for better more specific message.
-1 for extra param, why that could not be fixed by adding default remote to source repo? What's the use case?
Let's start with catching that error and re-raising something better.
The place to wrap an exception in `external_repo()` around the `yield`. 
@Suor @efiop if we allow non-cached artifacts to be pulled from an external repo, why would we require any remotes at all? The case can (and we had something like this in the past) - use it to collect metrics and use `dvc metrics show` exclusively. And other cases, of course.

+1 for improving messages.
Btw, it's the second time someone is asking us about adding a parameter to specify remote that should be used for an external repo. Just for the record.
Specifically this one is related: https://github.com/iterative/dvc/issues/2466
Let's discuss remote function param or cli in #2466. And leave this issue for message only.

Commit message: Update dvc/exceptions.py

Co-Authored-By: Ruslan Kuprieiev <kupruser@gmail.com>

Patch to review:
diff --git a/dvc/exceptions.py b/dvc/exceptions.py
index 07a0ce8061..45322bbe57 100644
--- a/dvc/exceptions.py
+++ b/dvc/exceptions.py
@@ -328,3 +328,12 @@ def __init__(self, target_infos):
 
 class CollectCacheError(DvcException):
     pass
+
+
+class RemoteNotSpecifiedInExternalRepoError(DvcException):
+    def __init__(self, url):
+        super(RemoteNotSpecifiedInExternalRepoError, self).__init__(
+            "No DVC remote is specified in the target repository '{}'".format(
+                url
+            )
+        )
diff --git a/dvc/external_repo.py b/dvc/external_repo.py
index ccdadf6e6b..6fab519dff 100644
--- a/dvc/external_repo.py
+++ b/dvc/external_repo.py
@@ -7,6 +7,8 @@
 
 from funcy import retry
 
+from dvc.config import NoRemoteError
+from dvc.exceptions import RemoteNotSpecifiedInExternalRepoError
 from dvc.utils import remove
 
 
@@ -19,7 +21,10 @@ def external_repo(url=None, rev=None, rev_lock=None, cache_dir=None):
 
     path = _external_repo(url=url, rev=rev_lock or rev, cache_dir=cache_dir)
     repo = Repo(path)
-    yield repo
+    try:
+        yield repo
+    except NoRemoteError:
+        raise RemoteNotSpecifiedInExternalRepoError(url)
     repo.close()
 
 


Code review comments:
diff_hunk: @@ -19,7 +21,10 @@ def external_repo(url=None, rev=None, rev_lock=None, cache_dir=None):
 
     path = _external_repo(url=url, rev=rev_lock or rev, cache_dir=cache_dir)
     repo = Repo(path)
-    yield repo
+    try:
+        yield repo
+    except NoRemoteError:
+        raise RemoteNotSpecifiedInExternalRepoError(url)
path: dvc/external_repo.py
text: @user1:
Just so we can get the traceback if we need it
```suggestion
        raise RemoteNotSpecifiedInExternalRepoError(url, cause=exc)
```