Repository: scikit-learn/scikit-learn
Pull request: FIX introduce a refresh_cache param to `fetch_...` functions.
This kinda fixes #14177. 

This does not change the warning message. But it introduces a `refresh_cache` parameter to the `fetch_...` functions that download and persist the data using `joblib`.

The proposal is to add this parameter, with some variation after reviews:

```
+    refresh_cache : str or bool, optional (default='joblib')
+        - ``True``: remove the previously downloaded data, and fetche it again.
+        - ``'joblib'``: only re-fetch the data if the previously downloaded
+          data has been persisted using the previously vendored `joblib`.
+        - ``False``: do not re-fetch the data.
+        
+        From version 0.23, ``'joblib'`` as an input value will be ignored and
+        assumed ``False``.
+
+        .. versionadded:: 0.21.3
```

I've changed only one of the dataset files, will fix the others once we agree on a solution.

@glemaitre @jnothman 

Problem statement:
Better warning message with deprecation of sklearn.externals._joblib
When loading the olivetti dataset, I got the deprecation warning:

```python
       "sklearn.externals.joblib is deprecated in 0.21 and will be removed "
       "in 0.23. Please import this functionality directly from joblib, "
       "which can be installed with: pip install joblib. If this warning is "
       "raised when loading pickled models, you may need to re-serialize "
       "those models with scikit-learn 0.21+."
```

It is due that the dataset was downloaded and pickled with an old scikit-learn. I have 2 suggestions:

1. "you may need to re-serialize those models with scikit-learn 0.21+" does not seem enough. We should mention that the models should be serialized with sklearn 0.21+ and joblib directly (externals.joblib is still existing).
2. It might be interesting to detect the case of the dataset. It does not have anything to do with the models and the user might wonder what is going on. If we detect the warning after calling `fetch_***` we could first remove the pickle and re-pickle using joblib which will avoid raising the deprecation warning after.

Hints from issue discussion:
Another point which we could improve is to tell the user where those data are located. I don't think most people know where to go and delete the files.
We are just mentioned the following:

```
Specify another download and cache folder for the datasets. By default all scikit-learn data is stored in ‘~/scikit_learn_data’ subfolders.
```

I might not make it easy for Windows users to know what mean `~/`.
Yes, but that's hidden in the docstring of the parameter, and most users would just call the function with the default value, then get the warning message, and not know how to follow up with it.
Oh I see. Yes you are right.
I would be okay to detect this case and re-cache over a deprecation
period... (but we have to also allow for the cache not being writable, I
think.)

It could even go into 0.21.3

> I would be okay to detect this case and re-cache over a deprecation period... (but we have to also allow for the cache not being writable, I think.)

You mean to automatically re-cache now, until a certain version? or the other way around?
I think re-cache now until a certain version??

Sounds good to me, I'll get on it :)
Thanks @adrinjalali

Commit message: remove param

Patch to review:
diff --git a/sklearn/datasets/base.py b/sklearn/datasets/base.py
index 0b8f73c86117b..f519862b72d56 100644
--- a/sklearn/datasets/base.py
+++ b/sklearn/datasets/base.py
@@ -10,6 +10,7 @@
 import csv
 import sys
 import shutil
+import warnings
 from collections import namedtuple
 from os import environ, listdir, makedirs
 from os.path import dirname, exists, expanduser, isdir, join, splitext
@@ -919,3 +920,25 @@ def _fetch_remote(remote, dirname=None):
                       "file may be corrupted.".format(file_path, checksum,
                                                       remote.checksum))
     return file_path
+
+
+def _refresh_cache(path):
+    # REMOVE in v0.23
+    import joblib
+    samples_path = _pkl_filepath(path, "samples")
+    targets_path = _pkl_filepath(path, "targets")
+    msg = "sklearn.externals.joblib is deprecated in 0.21"
+    with warnings.catch_warnings(record=True) as warns:
+        X = joblib.load(samples_path)
+        y = joblib.load(targets_path)
+
+        refresh_needed = any([str(x.message).startswith(msg) for x in warns])
+
+    if refresh_needed:
+        try:
+            joblib.dump(X, samples_path, compress=9)
+            joblib.dump(y, samples_path, compress=9)
+        except IOError:
+            pass
+
+    return X, y
diff --git a/sklearn/datasets/covtype.py b/sklearn/datasets/covtype.py
index 9d995810bee3f..24a9c8dfc108f 100644
--- a/sklearn/datasets/covtype.py
+++ b/sklearn/datasets/covtype.py
@@ -25,6 +25,7 @@
 from .base import get_data_home
 from .base import _fetch_remote
 from .base import RemoteFileMetadata
+from .base import _refresh_cache
 from ..utils import Bunch
 from .base import _pkl_filepath
 from ..utils import check_random_state
@@ -125,8 +126,10 @@ def fetch_covtype(data_home=None, download_if_missing=True,
     try:
         X, y
     except NameError:
-        X = joblib.load(samples_path)
-        y = joblib.load(targets_path)
+        X, y = _refresh_cache(covtype_dir)
+        # Revert to the following two lines in v0.23
+        # X = joblib.load(samples_path)
+        # y = joblib.load(targets_path)
 
     if shuffle:
         ind = np.arange(X.shape[0])


Code review comments:
diff_hunk: @@ -919,3 +920,25 @@ def _fetch_remote(remote, dirname=None):
                       "file may be corrupted.".format(file_path, checksum,
                                                       remote.checksum))
     return file_path
+
+
+def _refresh_cache(path):
path: sklearn/datasets/base.py
text: @user1:
you put this function in base.py but actually it's designed only for ``fetch_covtype``?