Repository: huggingface/datasets
Pull request: Fix manual download instructions
This PR replaces the static `DatasetBulider` variable `MANUAL_DOWNLOAD_INSTRUCTIONS` by a property function `manual_download_instructions()`. 

Some datasets like XTREME and all WMT need the manual data dir only for a small fraction of the possible configs.

After some brainstorming with @mariamabarham and @lhoestq, we came to the conclusion that having a property function `manual_download_instructions()` gives us more flexibility to decide on a per config basis in the dataset builder if manual download instructions are needed.

Also this PR should unblock solves a bug with `wmt16 - ro-en` 
@sshleifer from this branch you should be able to succesfully run

```python 
import nlp 
ds = nlp.load_dataset('./datasets/wmt16', 'ro-en')
```

and once this PR is merged S3 should be synched so that 

```python
import nlp
ds = nlp.load_dataset("wmt16", "ro-en")
```

works as well.

**Important**: Since `MANUAL_DOWNLOAD_INSTRUCTIONS` was not really exposed to the user, this PR should not be a problem regarding backward compatibility.

Problem statement:
How can I load/find WMT en-romanian?
I believe it is from `wmt16`

When I run

```python
wmt = nlp.load_dataset('wmt16')
```
I get:
```python
AssertionError: The dataset wmt16 with config cs-en requires manual data. 
 Please follow the manual download instructions:   Some of the wmt configs here, require a manual download.
  Please look into wmt.py to see the exact path (and file name) that has to
  be downloaded.
  . 
 Manual data can be loaded with `nlp.load(wmt16, data_dir='<path/to/manual/data>')
```
There is no wmt.py,as the error message suggests, and wmt16.py doesn't have manual download instructions.

Any idea how to do this?

Thanks in advance!

Hints from issue discussion:
I will take a look :-)

Commit message: fix xtreme

Patch to review:
diff --git a/datasets/c4/c4.py b/datasets/c4/c4.py
index 2ec2515f6a2..fb04e095966 100644
--- a/datasets/c4/c4.py
+++ b/datasets/c4/c4.py
@@ -126,15 +126,6 @@ def __init__(self, language, cc_versions=None, clean=True, realnewslike=False, w
 class C4(nlp.BeamBasedBuilder):
     """C4 dataset based on Common Crawl."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-    For the WebText-like config, you must manually download 'OpenWebText.zip'
-    (from https://mega.nz/#F!EZZD0YwJ!9_PlEQzdMVLaNdKv_ICNVQ) and the Common Crawl
-    WET files from August 2018 to July 2019
-    (https://commoncrawl.org/the-data/get-started/) and place them in the
-    `manual_dir`.
-
-    """
-
     BUILDER_CONFIGS = [
         C4Config(language="en", description="English C4 dataset."),
         C4Config(
@@ -156,6 +147,15 @@ class C4(nlp.BeamBasedBuilder):
         ),
     ]
 
+    def manual_download_instructions(self):
+        return """\
+    For the WebText-like config, you must manually download 'OpenWebText.zip'
+    (from https://mega.nz/#F!EZZD0YwJ!9_PlEQzdMVLaNdKv_ICNVQ) and the Common Crawl
+    WET files from August 2018 to July 2019
+    (https://commoncrawl.org/the-data/get-started/) and place them in the
+    `manual_dir`.
+        """
+
     def _info(self):
         features = {
             "text": nlp.Value("string"),
@@ -194,7 +194,7 @@ def _split_generators(self, dl_manager, pipeline):
             if not os.path.exists(owt_path):
                 raise FileNotFoundError(
                     "{} does not exist. Make sure you insert a manual dir via `nlp.load('c4', data_dir=...)` that includes a file name {}. Manual download instructions: {})".format(
-                        owt_path, _OPENWEBTEXT_URLS_ZIP, self.MANUAL_DOWNLOAD_INSTRUCTIONS
+                        owt_path, _OPENWEBTEXT_URLS_ZIP, self.manual_download_instructions
                     )
                 )
             file_paths["openwebtext_urls_zip"] = dl_manager.extract(owt_path)
@@ -212,7 +212,7 @@ def _split_generators(self, dl_manager, pipeline):
             if not os.path.exists(cc_dir):
                 raise FileNotFoundError(
                     "{} does not exist. Make sure you insert a manual dir via `nlp.load('c4', data_dir=...)` that includes the files {}. Manual download instructions: {})".format(
-                        cc_dir, "*.warc.wet.gz", self.MANUAL_DOWNLOAD_INSTRUCTIONS
+                        cc_dir, "*.warc.wet.gz", self.manual_download_instructions
                     )
                 )
             logging.info("Adding %d WET files for manually downloaded version %s.", len(wet_files), cc_version)
diff --git a/datasets/c4/c4_utils.py b/datasets/c4/c4_utils.py
index 43537e6163d..2dc8fa0ce6b 100644
--- a/datasets/c4/c4_utils.py
+++ b/datasets/c4/c4_utils.py
@@ -26,12 +26,13 @@
 import threading
 
 import apache_beam as beam
-import langdetect
 import nltk
 import tensorflow.compat.v2 as tf
-import tldextract
 from absl import logging
 
+import langdetect
+import tldextract
+
 
 # WET file constants
 _PAGE_DELIMITER = "WARC/1.0"
diff --git a/datasets/cos_e/cos_e.py b/datasets/cos_e/cos_e.py
index 3b83ab3e2e8..fc3c7502177 100644
--- a/datasets/cos_e/cos_e.py
+++ b/datasets/cos_e/cos_e.py
@@ -51,19 +51,19 @@
 _CQA_V1_11_URL_TEST = "https://s3.amazonaws.com/commensenseqa/test_rand_split_no_answers.jsonl"
 
 _CQA_V1_0_URL_TRAIN = os.path.join(_COS_E_URL, "v1.0/train_rand_split.jsonl")
-_CQA_V1_0_URL_DEV = os.path.join(_COS_E_URL,"v1.0/dev_rand_split.jsonl")
+_CQA_V1_0_URL_DEV = os.path.join(_COS_E_URL, "v1.0/dev_rand_split.jsonl")
 _CQA_V1_0_URL_TEST = os.path.join(_COS_E_URL, "v1.0/test_rand_split_no_answers.jsonl")
 
 
-
 def _download_and_index_cqa(dl_manager, name):
     """Downloads CQA and returns it, indexed by id, for joining with Cos-E."""
 
     downloaded_files = dl_manager.download_and_extract(
-        {"cqa_train": _CQA_V1_11_URL_TRAIN if name == 'v1.11' else _CQA_V1_0_URL_TRAIN,
-          "cqa_dev": _CQA_V1_11_URL_DEV if name == 'v1.11' else _CQA_V1_0_URL_DEV,
-          "cqa_test": _CQA_V1_11_URL_TEST if name == 'v1.11' else _CQA_V1_0_URL_TEST
-         }
+        {
+            "cqa_train": _CQA_V1_11_URL_TRAIN if name == "v1.11" else _CQA_V1_0_URL_TRAIN,
+            "cqa_dev": _CQA_V1_11_URL_DEV if name == "v1.11" else _CQA_V1_0_URL_DEV,
+            "cqa_test": _CQA_V1_11_URL_TEST if name == "v1.11" else _CQA_V1_0_URL_TEST,
+        }
     )
 
     # NB: "cqa_test" is included in the files, but not in any of the CoS-E splits.
@@ -112,12 +112,14 @@ class CosE(nlp.GeneratorBasedBuilder):
 
     BUILDER_CONFIGS = [
         CosEConfig(
-            name="v1.0", description="cos-e version 1.0",
-            version=nlp.Version("1.0.0", "New split API (https://tensorflow.org/datasets/splits)")
+            name="v1.0",
+            description="cos-e version 1.0",
+            version=nlp.Version("1.0.0", "New split API (https://tensorflow.org/datasets/splits)"),
         ),
         CosEConfig(
-            name="v1.11", description="cos-e version 1.11",
-            version=nlp.Version("1.11.0", "New split API (https://tensorflow.org/datasets/splits)")
+            name="v1.11",
+            description="cos-e version 1.11",
+            version=nlp.Version("1.11.0", "New split API (https://tensorflow.org/datasets/splits)"),
         ),
     ]
 
@@ -145,14 +147,14 @@ def _split_generators(self, dl_manager):
         # NB: The CQA Dataset should be read only once, and only by callers who
         # want to _create_ the Cos-E dataset from scratch.
         cqa_indexed = _download_and_index_cqa(dl_manager, self.config.name)
-        if self.config.name == 'v1.11':
+        if self.config.name == "v1.11":
             files = dl_manager.download_and_extract(
                 {
                     "dev": [os.path.join(_COS_E_URL, "v1.11/cose_dev_v1.11_processed.jsonl")],
                     "train": [os.path.join(_COS_E_URL, "v1.11/cose_train_v1.11_processed.jsonl")],
                 }
             )
-        elif self.config.name == 'v1.0':
+        elif self.config.name == "v1.0":
             files = dl_manager.download_and_extract(
                 {
                     "dev": [os.path.join(_COS_E_URL, "v1.0/cose_dev_v1.0_processed.jsonl")],
@@ -160,7 +162,7 @@ def _split_generators(self, dl_manager):
                 }
             )
         else:
-            raise ValueError('Unknown config name')
+            raise ValueError("Unknown config name")
 
         # We use the CoS-E/CQA dev set as our validation set.
         return [
@@ -170,7 +172,6 @@ def _split_generators(self, dl_manager):
             nlp.SplitGenerator(
                 name=nlp.Split.VALIDATION, gen_kwargs={"files": files["dev"], "cqa_indexed": cqa_indexed},
             ),
-
         ]
 
     def _generate_examples(self, files, **kwargs):
diff --git a/datasets/newsroom/newsroom.py b/datasets/newsroom/newsroom.py
index 24e5d8a9ff9..084b7187c2f 100644
--- a/datasets/newsroom/newsroom.py
+++ b/datasets/newsroom/newsroom.py
@@ -81,7 +81,10 @@ class Newsroom(nlp.GeneratorBasedBuilder):
     """NEWSROOM Dataset."""
 
     VERSION = nlp.Version("1.0.0")
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
+
+    @property
+    def manual_download_instructions(self):
+        return """\
   You should download the dataset from http://lil.nlp.cornell.edu/newsroom/
   The webpage requires registration.
   To unzip the .tar file run `tar -zxvf complete.tar`. To unzip the .gz files
@@ -110,7 +113,7 @@ def _split_generators(self, dl_manager):
         if not os.path.exists(data_dir):
             raise FileNotFoundError(
                 "{} does not exist. Make sure you insert a manual dir via `nlp.load('newsroom', data_dir=...)` that includes files unzipped from the reclor zip. Manual download instructions: {}".format(
-                    data_dir, self.MANUAL_DOWNLOAD_INSTRUCTIONS
+                    data_dir, self.manual_download_instructions
                 )
             )
         return [
diff --git a/datasets/reclor/reclor.py b/datasets/reclor/reclor.py
index 79e112daa41..39bdd50002f 100644
--- a/datasets/reclor/reclor.py
+++ b/datasets/reclor/reclor.py
@@ -4,7 +4,6 @@
 
 import json
 import os
-from pathlib import Path
 
 import nlp
 
@@ -36,7 +35,10 @@ class Reclor(nlp.GeneratorBasedBuilder):
 
     # TODO(reclor): Set up version.
     VERSION = nlp.Version("0.1.0")
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
+
+    @property
+    def manual_download_instructions(self):
+        return """\
   to use ReClor you need to download it manually. Please go to its homepage (http://whyu.me/reclor/) fill the google 
   form and you will recive a download link and a password to extract it.Please extract all files in one folder and use the path folder in nlp.load('reclor', data_dir='path/to/folder/folder_name')
   """
@@ -76,7 +78,7 @@ def _split_generators(self, dl_manager):
         if not os.path.exists(data_dir):
             raise FileNotFoundError(
                 "{} does not exist. Make sure you insert a manual dir via `nlp.load('wikihow', data_dir=...)` that includes files unzipped from the reclor zip. Manual download instructions: {}".format(
-                    data_dir, self.MANUAL_DOWNLOAD_INSTRUCTIONS
+                    data_dir, self.manual_download_instructions
                 )
             )
         return [
diff --git a/datasets/ubuntu_dialogs_corpus/ubuntu_dialogs_corpus.py b/datasets/ubuntu_dialogs_corpus/ubuntu_dialogs_corpus.py
index 58474df2ca6..6aa7c9d547d 100644
--- a/datasets/ubuntu_dialogs_corpus/ubuntu_dialogs_corpus.py
+++ b/datasets/ubuntu_dialogs_corpus/ubuntu_dialogs_corpus.py
@@ -65,7 +65,10 @@ class UbuntuDialogsCorpus(nlp.GeneratorBasedBuilder):
             description="test and dev features",
         ),
     ]
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
+
+    @property
+    def manual_download_instructions(self):
+        return """\
   Please download the Ubuntu Dialog Corpus from https://github.com/rkadlec/ubuntu-ranking-dataset-creator. Run ./generate.sh -t -s -l to download the
    data. Others arguments are left to their default values here. Please save train.csv, test.csv and valid.csv in the same path"""
 
diff --git a/datasets/wikihow/wikihow.py b/datasets/wikihow/wikihow.py
index d67271344b4..b3c4532f1d7 100644
--- a/datasets/wikihow/wikihow.py
+++ b/datasets/wikihow/wikihow.py
@@ -86,17 +86,6 @@ def __init__(self, filename=None, **kwargs):
 class Wikihow(nlp.GeneratorBasedBuilder):
     """WikiHow: A Large Scale Text Summarization Dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  You need to manually download two wikihow files. An overview of which files to download can be seen at https://github.com/mahnazkoupaee/WikiHow-Dataset.
-  You need to download the following two files manually:
-    1) https://ucsb.app.box.com/s/ap23l8gafpezf4tq3wapr6u8241zz358 and save the file under <path/to/folder>/wikihowAll.csv
-    2) https://ucsb.app.box.com/s/7yq601ijl1lzvlfu4rjdbbxforzd2oag and save the file under <path/to/folder>/wikihowSep.csv
-
-  The <path/to/folder> can e.g. be "~/manual_wikihow_data".
-
-  Wikihow can then be loaded using the following command `nlp.load("wikihow", data_file="<path/to/folder>")`.
-  """
-
     BUILDER_CONFIGS = [
         WikihowConfig(
             name="all",
@@ -107,6 +96,19 @@ class Wikihow(nlp.GeneratorBasedBuilder):
         WikihowConfig(name="sep", filename="wikihowSep.csv", description="use each paragraph and its summary."),
     ]
 
+    @property
+    def manual_download_instructions(self):
+        return """\
+  You need to manually download two wikihow files. An overview of which files to download can be seen at https://github.com/mahnazkoupaee/WikiHow-Dataset.
+  You need to download the following two files manually:
+    1) https://ucsb.app.box.com/s/ap23l8gafpezf4tq3wapr6u8241zz358 and save the file under <path/to/folder>/wikihowAll.csv
+    2) https://ucsb.app.box.com/s/7yq601ijl1lzvlfu4rjdbbxforzd2oag and save the file under <path/to/folder>/wikihowSep.csv
+
+  The <path/to/folder> can e.g. be "~/manual_wikihow_data".
+
+  Wikihow can then be loaded using the following command `nlp.load("wikihow", data_file="<path/to/folder>")`.
+  """
+
     def _info(self):
         feature_names = [_DOCUMENT, _SUMMARY, "title"]
         if self.config.name == "sep":
@@ -135,7 +137,7 @@ def _split_generators(self, dl_manager):
         if not os.path.exists(path_to_manual_file):
             raise FileNotFoundError(
                 "{} does not exist. Make sure you insert a manual dir via `nlp.load('wikihow', data_dir=...)` that includes a file name {}. Manual download instructions: {})".format(
-                    path_to_manual_file, self.config.filename, self.MANUAL_DOWNLOAD_INSTRUCTIONS
+                    path_to_manual_file, self.config.filename, self.manual_download_instructions
                 )
             )
         return [
diff --git a/datasets/wmt14/wmt14.py b/datasets/wmt14/wmt14.py
index ed61b21ff53..c653e6e4cf0 100644
--- a/datasets/wmt14/wmt14.py
+++ b/datasets/wmt14/wmt14.py
@@ -55,6 +55,12 @@ class Wmt14(Wmt):
         for l1, l2 in _LANGUAGE_PAIRS
     ]
 
+    @property
+    def manual_download_instructions(self):
+        if self.config.language_pair[1] in ["cs", "hi", "ru"]:
+            return "Please download the data manually as explained. TODO(PVP)"
+        return None
+
     @property
     def _subsets(self):
         return {
diff --git a/datasets/wmt14/wmt_utils.py b/datasets/wmt14/wmt_utils.py
index 3649a621c1d..ebe00219541 100644
--- a/datasets/wmt14/wmt_utils.py
+++ b/datasets/wmt14/wmt_utils.py
@@ -668,12 +668,6 @@ def __init__(self, url=None, citation=None, description=None, language_pair=(Non
 class Wmt(ABC, nlp.GeneratorBasedBuilder):
     """WMT translation dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  Some of the wmt configs here, require a manual download.
-  Please look into wmt.py to see the exact path (and file name) that has to
-  be downloaded.
-  """
-
     def __init__(self, *args, **kwargs):
         if type(self) == Wmt and "config" not in kwargs:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
diff --git a/datasets/wmt15/wmt15.py b/datasets/wmt15/wmt15.py
index b6ccf71a240..2f49726057b 100644
--- a/datasets/wmt15/wmt15.py
+++ b/datasets/wmt15/wmt15.py
@@ -53,6 +53,11 @@ class Wmt15(Wmt):
         for l1, l2 in _LANGUAGE_PAIRS
     ]
 
+    @property
+    def manual_download_instructions(self):
+        if self.config.language_pair[1] in ["cs", "hi", "ru"]:
+            return "Please download the data manually as explained. TODO(PVP)"
+
     @property
     def _subsets(self):
         return {
@@ -69,5 +74,5 @@ def _subsets(self):
                 "wikiheadlines_ru",
             ],
             nlp.Split.VALIDATION: ["newsdev2015", "newsdiscussdev2015", "newstest2014"],
-            nlp.Split.TEST: ["newstest2015", "newsdiscusstest2015",],
+            nlp.Split.TEST: ["newstest2015", "newsdiscusstest2015"],
         }
diff --git a/datasets/wmt15/wmt_utils.py b/datasets/wmt15/wmt_utils.py
index 3649a621c1d..ebe00219541 100644
--- a/datasets/wmt15/wmt_utils.py
+++ b/datasets/wmt15/wmt_utils.py
@@ -668,12 +668,6 @@ def __init__(self, url=None, citation=None, description=None, language_pair=(Non
 class Wmt(ABC, nlp.GeneratorBasedBuilder):
     """WMT translation dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  Some of the wmt configs here, require a manual download.
-  Please look into wmt.py to see the exact path (and file name) that has to
-  be downloaded.
-  """
-
     def __init__(self, *args, **kwargs):
         if type(self) == Wmt and "config" not in kwargs:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
diff --git a/datasets/wmt16/wmt_utils.py b/datasets/wmt16/wmt_utils.py
index 3649a621c1d..c3f95ea85c8 100644
--- a/datasets/wmt16/wmt_utils.py
+++ b/datasets/wmt16/wmt_utils.py
@@ -668,12 +668,6 @@ def __init__(self, url=None, citation=None, description=None, language_pair=(Non
 class Wmt(ABC, nlp.GeneratorBasedBuilder):
     """WMT translation dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  Some of the wmt configs here, require a manual download.
-  Please look into wmt.py to see the exact path (and file name) that has to
-  be downloaded.
-  """
-
     def __init__(self, *args, **kwargs):
         if type(self) == Wmt and "config" not in kwargs:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
@@ -826,14 +820,14 @@ def _get_local_paths(dataset, extract_dirs):
                     or ss_name.startswith("wikititles_v1")
                 ):
                     sub_generator = functools.partial(_parse_tsv, language_pair=self.config.language_pair)
-                elif "tmx" in fname or ss_name.startswith("paracrawl_v3"):
+                elif "tmx" in fname or ss_name.startswith("paracrawl_v3") or ss_name.startswith("setimes_2"):
                     sub_generator = _parse_tmx
                 elif ss_name.startswith("wikiheadlines"):
                     sub_generator = _parse_wikiheadlines
                 else:
-                    raise ValueError("Unsupported file format: %s" % fname)
+                    raise ValueError(f"Unsupported file format: {fname} for {ss_name}")
             else:
-                raise ValueError("Invalid number of files: %d" % len(files))
+                raise ValueError(f"Invalid number of files: {len(files)}")
 
             for sub_key, ex in sub_generator(*files):
                 if not all(ex.values()):
diff --git a/datasets/wmt17/wmt17.py b/datasets/wmt17/wmt17.py
index e4e97401553..8b92a482376 100644
--- a/datasets/wmt17/wmt17.py
+++ b/datasets/wmt17/wmt17.py
@@ -53,6 +53,11 @@ class Wmt17(Wmt):
         for l1, l2 in _LANGUAGE_PAIRS
     ]
 
+    @property
+    def manual_download_instructions(self):
+        if self.config.language_pair[1] in ["cs", "hi", "ru"]:
+            return "Please download the data manually as explained. TODO(PVP)"
+
     @property
     def _subsets(self):
         return {
diff --git a/datasets/wmt17/wmt_utils.py b/datasets/wmt17/wmt_utils.py
index 3649a621c1d..ebe00219541 100644
--- a/datasets/wmt17/wmt_utils.py
+++ b/datasets/wmt17/wmt_utils.py
@@ -668,12 +668,6 @@ def __init__(self, url=None, citation=None, description=None, language_pair=(Non
 class Wmt(ABC, nlp.GeneratorBasedBuilder):
     """WMT translation dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  Some of the wmt configs here, require a manual download.
-  Please look into wmt.py to see the exact path (and file name) that has to
-  be downloaded.
-  """
-
     def __init__(self, *args, **kwargs):
         if type(self) == Wmt and "config" not in kwargs:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
diff --git a/datasets/wmt18/wmt18.py b/datasets/wmt18/wmt18.py
index acfe708def1..0566d824247 100644
--- a/datasets/wmt18/wmt18.py
+++ b/datasets/wmt18/wmt18.py
@@ -58,6 +58,11 @@ class Wmt18(Wmt):
         for l1, l2 in _LANGUAGE_PAIRS
     ]
 
+    @property
+    def manual_download_instructions(self):
+        if self.config.language_pair[1] in ["cs", "hi", "ru"]:
+            return "Please download the data manually as explained. TODO(PVP)"
+
     @property
     def _subsets(self):
         return {
diff --git a/datasets/wmt18/wmt_utils.py b/datasets/wmt18/wmt_utils.py
index 3649a621c1d..ebe00219541 100644
--- a/datasets/wmt18/wmt_utils.py
+++ b/datasets/wmt18/wmt_utils.py
@@ -668,12 +668,6 @@ def __init__(self, url=None, citation=None, description=None, language_pair=(Non
 class Wmt(ABC, nlp.GeneratorBasedBuilder):
     """WMT translation dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  Some of the wmt configs here, require a manual download.
-  Please look into wmt.py to see the exact path (and file name) that has to
-  be downloaded.
-  """
-
     def __init__(self, *args, **kwargs):
         if type(self) == Wmt and "config" not in kwargs:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
diff --git a/datasets/wmt19/wmt19.py b/datasets/wmt19/wmt19.py
index d18c0b32339..44d051e2d49 100644
--- a/datasets/wmt19/wmt19.py
+++ b/datasets/wmt19/wmt19.py
@@ -50,6 +50,11 @@ class Wmt19(Wmt):
         for l1, l2 in _LANGUAGE_PAIRS
     ]
 
+    @property
+    def manual_download_instructions(self):
+        if self.config.language_pair[1] in ["cs", "hi", "ru"]:
+            return "Please download the data manually as explained. TODO(PVP)"
+
     @property
     def _subsets(self):
         return {
diff --git a/datasets/wmt19/wmt_utils.py b/datasets/wmt19/wmt_utils.py
index 3649a621c1d..ebe00219541 100644
--- a/datasets/wmt19/wmt_utils.py
+++ b/datasets/wmt19/wmt_utils.py
@@ -668,12 +668,6 @@ def __init__(self, url=None, citation=None, description=None, language_pair=(Non
 class Wmt(ABC, nlp.GeneratorBasedBuilder):
     """WMT translation dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  Some of the wmt configs here, require a manual download.
-  Please look into wmt.py to see the exact path (and file name) that has to
-  be downloaded.
-  """
-
     def __init__(self, *args, **kwargs):
         if type(self) == Wmt and "config" not in kwargs:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
diff --git a/datasets/wmt_t2t/wmt_t2t.py b/datasets/wmt_t2t/wmt_t2t.py
index f6641ed2217..18e25e0d29b 100644
--- a/datasets/wmt_t2t/wmt_t2t.py
+++ b/datasets/wmt_t2t/wmt_t2t.py
@@ -50,6 +50,11 @@ class WmtT2t(Wmt):
         )
     ]
 
+    @property
+    def manual_download_instructions(self):
+        if self.config.language_pair[1] in ["cs", "hi", "ru"]:
+            return "Please download the data manually as explained. TODO(PVP)"
+
     @property
     def _subsets(self):
         return {
diff --git a/datasets/wmt_t2t/wmt_utils.py b/datasets/wmt_t2t/wmt_utils.py
index 3649a621c1d..ebe00219541 100644
--- a/datasets/wmt_t2t/wmt_utils.py
+++ b/datasets/wmt_t2t/wmt_utils.py
@@ -668,12 +668,6 @@ def __init__(self, url=None, citation=None, description=None, language_pair=(Non
 class Wmt(ABC, nlp.GeneratorBasedBuilder):
     """WMT translation dataset."""
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-  Some of the wmt configs here, require a manual download.
-  Please look into wmt.py to see the exact path (and file name) that has to
-  be downloaded.
-  """
-
     def __init__(self, *args, **kwargs):
         if type(self) == Wmt and "config" not in kwargs:  # pylint: disable=unidiomatic-typecheck
             raise ValueError(
diff --git a/datasets/xsum/xsum.py b/datasets/xsum/xsum.py
index 4815c102e8c..7faa7d6b056 100644
--- a/datasets/xsum/xsum.py
+++ b/datasets/xsum/xsum.py
@@ -79,12 +79,12 @@ class Xsum(nlp.GeneratorBasedBuilder):
     VERSION = nlp.Version("1.1.0")
     SUPPORTED_VERSIONS = [nlp.Version("1.0.0", "Dataset without cleaning.")]
 
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
+    @property
+    def manual_download_instructions(self):
+        return """\
   Detailed download instructions (which require running a custom script) are
   here:
   https://github.com/EdinburghNLP/XSum/blob/master/XSum-Dataset/README.md . Please make sure you run download-bbc-articles.py and parse-bbc-html-data.py scripts
- 
-
   """
 
     def _info(self):
@@ -105,7 +105,7 @@ def _split_generators(self, dl_manager):
         if not os.path.exists(downloaded_path):
             raise FileNotFoundError(
                 "{} does not exist. Make sure you indicate the data_dir as  `nlp.load('xsum', data_dir=...), which points to your downloded dataset'. Manual download instructions: {})".format(
-                    downloaded_path, self.MANUAL_DOWNLOAD_INSTRUCTIONS
+                    downloaded_path, self.manual_download_instructions
                 )
             )
         return [
diff --git a/datasets/xtreme/xtreme.py b/datasets/xtreme/xtreme.py
index c3fc42c85dc..ee270f7470b 100644
--- a/datasets/xtreme/xtreme.py
+++ b/datasets/xtreme/xtreme.py
@@ -419,11 +419,6 @@ class Xtreme(nlp.GeneratorBasedBuilder):
 
     # TODO(xtreme): Set up version.
     VERSION = nlp.Version("0.1.0")
-    MANUAL_DOWNLOAD_INSTRUCTIONS = """\
-     You need to manually download the AmazonPhotos.zip file on Amazon Cloud Drive
-     (https://www.amazon.com/clouddrive/share/d3KGCRCIYwhKJF0H3eWA26hjg2ZCRhjpEQtDL70FSBN) and save the file under <path/to/folder>AmazonPhotos.zip
-
-    """
     BUILDER_CONFIGS = [
         XtremeConfig(
             name=name,
@@ -436,6 +431,15 @@ class Xtreme(nlp.GeneratorBasedBuilder):
         for name in _NAMES
     ]
 
+    @property
+    def manual_download_instructions(self):
+        if self.config.name.startswith("PAN-X"):
+            return """\
+             You need to manually download the AmazonPhotos.zip file on Amazon Cloud Drive
+             (https://www.amazon.com/clouddrive/share/d3KGCRCIYwhKJF0H3eWA26hjg2ZCRhjpEQtDL70FSBN) and save the file under <path/to/folder>AmazonPhotos.zip
+            """
+        return None
+
     def _info(self):
         # TODO(xtreme): Specifies the nlp.DatasetInfo object
         features = {text_feature: nlp.Value("string") for text_feature in six.iterkeys(self.config.text_features)}
@@ -714,7 +718,7 @@ def _split_generators(self, dl_manager):
             if not os.path.exists(panx_path):
                 raise FileNotFoundError(
                     "{} does not exist. Make sure you insert a manual dir via `nlp.load('wikihow', data_dir=...)` that includes {}. Manual download instructions: {}".format(
-                        panx_path, _PAN_X_FOLDER, self.MANUAL_DOWNLOAD_INSTRUCTIONS
+                        panx_path, _PAN_X_FOLDER, self.manual_download_instructions
                     )
                 )
 
diff --git a/src/nlp/builder.py b/src/nlp/builder.py
index 983d09ff43f..a2e14c455b1 100644
--- a/src/nlp/builder.py
+++ b/src/nlp/builder.py
@@ -111,7 +111,6 @@ class DatasetBuilder:
     # This field should contain a string with user instructions, including
     # the list of files that should be present. It will be
     # displayed in the dataset documentation.
-    MANUAL_DOWNLOAD_INSTRUCTIONS = None
 
     def __init__(
         self, cache_dir=None, name=None, **config_kwargs,
@@ -160,8 +159,8 @@ def __init__(
                 os.rmdir(self._cache_dir)
 
     @property
-    def does_require_manual_download(self):
-        return hasattr(self, "MANUAL_DOWNLOAD_INSTRUCTIONS") and (self.MANUAL_DOWNLOAD_INSTRUCTIONS is not None)
+    def manual_download_instructions(self) -> Optional[str]:
+        return None
 
     @classmethod
     def get_all_exported_dataset_infos(cls) -> dict:
@@ -416,11 +415,11 @@ def incomplete_dir(dirname):
                 dataset_name=self.name, download_config=download_config, data_dir=self.config.data_dir
             )
 
-        if self.does_require_manual_download:
+        if self.manual_download_instructions is not None:
             assert (
                 dl_manager.manual_dir is not None
             ), "The dataset {} with config {} requires manual data. \n Please follow the manual download instructions: {}. \n Manual data can be loaded with `nlp.load({}, data_dir='<path/to/manual/data>')".format(
-                self.name, self.config.name, self.MANUAL_DOWNLOAD_INSTRUCTIONS, self.name
+                self.name, self.config.name, self.manual_download_instructions, self.name
             )
 
         # Create a tmp dir and rename to self._cache_dir on successful exit.
@@ -483,7 +482,7 @@ def _download_and_prepare(self, dl_manager, verify_infos, **prepare_split_kwargs
                 # Prepare split will record examples associated to the split
                 self._prepare_split(split_generator, **prepare_split_kwargs)
             except OSError:
-                raise OSError("Cannot find data file. " + (self.MANUAL_DOWNLOAD_INSTRUCTIONS or ""))
+                raise OSError("Cannot find data file. " + (self.manual_download_instructions or ""))
 
         if verify_infos:
             verify_splits(self.info.splits, split_dict)


Code review comments:
diff_hunk: @@ -107,6 +96,19 @@ class Wikihow(nlp.GeneratorBasedBuilder):
         WikihowConfig(name="sep", filename="wikihowSep.csv", description="use each paragraph and its summary."),
     ]
 
+    @property
+    def manual_download_instructions(self):
+        return """\
+  You need to manually download two wikihow files. An overview of which files to download can be seen at https://github.com/mahnazkoupaee/WikiHow-Dataset.
+  You need to download the following two files manually:
+    1) https://ucsb.app.box.com/s/ap23l8gafpezf4tq3wapr6u8241zz358 and save the file under <path/to/folder>/wikihowAll.csv
+    2) https://ucsb.app.box.com/s/7yq601ijl1lzvlfu4rjdbbxforzd2oag and save the file under <path/to/folder>/wikihowSep.csv
+
+  The <path/to/folder> can e.g. be "~/manual_wikihow_data".
+
+  Wikihow can then be loaded using the following command `nlp.load("wikihow", data_file="<path/to/folder>")`.
path: datasets/wikihow/wikihow.py
text: @user1:
```suggestion
  Wikihow can then be loaded using the following command `nlp.load("wikihow", data_dir="<path/to/folder>")`.
```
It should be `data_dir` ?

diff_hunk: @@ -156,6 +147,15 @@ class C4(nlp.BeamBasedBuilder):
         ),
     ]
 
+    def manual_download_instructions(self):
+        return """\
+    For the WebText-like config, you must manually download 'OpenWebText.zip'
+    (from https://mega.nz/#F!EZZD0YwJ!9_PlEQzdMVLaNdKv_ICNVQ) and the Common Crawl
+    WET files from August 2018 to July 2019
+    (https://commoncrawl.org/the-data/get-started/) and place them in the
+    `manual_dir`.
path: datasets/c4/c4.py
text: @user1:
shall we replace mentions of `manual_dir` with `data_dir` ?