codecov-io: # [Codecov](https://codecov.io/gh/openml/openml-python/pull/677?src=pr&el=h1) Report
> Merging [#677](https://codecov.io/gh/openml/openml-python/pull/677?src=pr&el=desc) into [develop](https://codecov.io/gh/openml/openml-python/commit/813daebea2d0c4932641f013ef79ba0ca72a9f46?src=pr&el=desc) will **decrease** coverage by `0.03%`.
> The diff coverage is `94.73%`.

[![Impacted file tree graph](https://codecov.io/gh/openml/openml-python/pull/677/graphs/tree.svg?width=650&token=IlImE4jvlP&height=150&src=pr)](https://codecov.io/gh/openml/openml-python/pull/677?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           develop    #677      +/-   ##
==========================================
- Coverage    90.54%   90.5%   -0.04%     
==========================================
  Files           36      36              
  Lines         3743    3730      -13     
==========================================
- Hits          3389    3376      -13     
  Misses         354     354
```


| [Impacted Files](https://codecov.io/gh/openml/openml-python/pull/677?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [openml/tasks/task.py](https://codecov.io/gh/openml/openml-python/pull/677/diff?src=pr&el=tree#diff-b3Blbm1sL3Rhc2tzL3Rhc2sucHk=) | `94.77% <100%> (ø)` | :arrow_up: |
| [openml/datasets/dataset.py](https://codecov.io/gh/openml/openml-python/pull/677/diff?src=pr&el=tree#diff-b3Blbm1sL2RhdGFzZXRzL2RhdGFzZXQucHk=) | `88.12% <93.33%> (-0.47%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/openml/openml-python/pull/677?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/openml/openml-python/pull/677?src=pr&el=footer). Last update [813daeb...b2fb382](https://codecov.io/gh/openml/openml-python/pull/677?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/examples/datasets_tutorial.py b/examples/datasets_tutorial.py
index dd24e349..4d340de7 100644
--- a/examples/datasets_tutorial.py
+++ b/examples/datasets_tutorial.py
@@ -60,10 +60,9 @@ print(dataset.description[:500])
 # controlled with the parameter ``dataset_format`` which can be either 'array'
 # (default) or 'dataframe'. Let's first build our dataset from a NumPy array
 # and manually create a dataframe.
-X, y, attribute_names = dataset.get_data(
+X, y, categorical_indicator, attribute_names = dataset.get_data(
     dataset_format='array',
-    target=dataset.default_target_attribute,
-    return_attribute_names=True,
+    target=dataset.default_target_attribute
 )
 eeg = pd.DataFrame(X, columns=attribute_names)
 eeg['class'] = y
@@ -72,8 +71,10 @@ print(eeg[:10])
 ############################################################################
 # Instead of manually creating the dataframe, you can already request a
 # dataframe with the correct dtypes.
-X, y = dataset.get_data(target=dataset.default_target_attribute,
-                        dataset_format='dataframe')
+X, y, categorical_indicator, attribute_names = dataset.get_data(
+    target=dataset.default_target_attribute,
+    dataset_format='dataframe'
+)
 print(X.head())
 print(X.info())
 
diff --git a/examples/flows_and_runs_tutorial.py b/examples/flows_and_runs_tutorial.py
index badddf1a..d196c30e 100644
--- a/examples/flows_and_runs_tutorial.py
+++ b/examples/flows_and_runs_tutorial.py
@@ -22,7 +22,7 @@ from sklearn import ensemble, neighbors, preprocessing, pipeline, tree
 openml.config.start_using_configuration_for_example()
 # NOTE: We are using dataset 68 from the test server: https://test.openml.org/d/68
 dataset = openml.datasets.get_dataset(68)
-X, y = dataset.get_data(
+X, y, categorical_indicator, attribute_names = dataset.get_data(
     dataset_format='array',
     target=dataset.default_target_attribute
 )
@@ -34,13 +34,12 @@ clf.fit(X, y)
 #
 # * e.g. categorical features -> do feature encoding
 dataset = openml.datasets.get_dataset(17)
-X, y, categorical = dataset.get_data(
+X, y, categorical_indicator, attribute_names = dataset.get_data(
     dataset_format='array',
-    target=dataset.default_target_attribute,
-    return_categorical_indicator=True,
+    target=dataset.default_target_attribute
 )
-print("Categorical features: %s" % categorical)
-enc = preprocessing.OneHotEncoder(categorical_features=categorical)
+print("Categorical features: {}".format(categorical_indicator))
+enc = preprocessing.OneHotEncoder(categorical_features=categorical_indicator)
 X = enc.fit_transform(X)
 clf.fit(X, y)
 
diff --git a/openml/datasets/dataset.py b/openml/datasets/dataset.py
index cb12d3af..b6833a51 100644
--- a/openml/datasets/dataset.py
+++ b/openml/datasets/dataset.py
@@ -4,7 +4,7 @@ import io
 import logging
 import os
 import pickle
-from typing import List, Optional, Union
+from typing import List, Optional, Union, Tuple, Iterable
 
 import arff
 import numpy as np
@@ -419,29 +419,31 @@ class OpenMLDataset(object):
         from .functions import _get_dataset_arff
         self.data_file = _get_dataset_arff(self)
 
-    def get_data(self, target: Optional[Union[List[str], str]] = None,
-                 include_row_id: bool = False,
-                 include_ignore_attributes: bool = False,
-                 return_categorical_indicator: bool = False,
-                 return_attribute_names: bool = False,
-                 dataset_format: str = None):
+    def get_data(
+            self,
+            target: Optional[Union[List[str], str]] = None,
+            include_row_id: bool = False,
+            include_ignore_attributes: bool = False,
+            dataset_format: str = "dataframe",
+    ) -> Tuple[
+            Union[np.ndarray, pd.DataFrame, scipy.sparse.csr_matrix],
+            Optional[Union[np.ndarray, pd.DataFrame]],
+            List[bool],
+            List[str]
+    ]:
         """ Returns dataset content as dataframes or sparse matrices.
 
         Parameters
         ----------
-        target : string, list of strings or None (default=None)
-            Name of target column(s) to separate from the data.
+        target : string, List[str] or None (default=None)
+            Name of target column to separate from the data.
+            Splitting multiple columns is currently not supported.
         include_row_id : boolean (default=False)
             Whether to include row ids in the returned dataset.
         include_ignore_attributes : boolean (default=False)
             Whether to include columns that are marked as "ignore"
             on the server in the dataset.
-        return_categorical_indicator : boolean (default=False)
-            Whether to return a boolean mask indicating which features are
-            categorical.
-        return_attribute_names : boolean (default=False)
-            Whether to return attribute names.
-        dataset_format : string, optional
+        dataset_format : string (default='dataframe')
             The format of returned dataset.
             If ``array``, the returned dataset will be a NumPy array or a SciPy sparse matrix.
             If ``dataframe``, the returned dataset will be a Pandas DataFrame or SparseDataFrame.
@@ -450,22 +452,13 @@ class OpenMLDataset(object):
         -------
         X : ndarray, dataframe, or sparse matrix, shape (n_samples, n_columns)
             Dataset
-        y : ndarray or series, shape (n_samples,)
-            Target column(s). Only returned if target is not None.
+        y : ndarray or pd.Series, shape (n_samples, ) or None
+            Target column
         categorical_indicator : boolean ndarray
             Mask that indicate categorical features.
-            Only returned if return_categorical_indicator is True.
-        return_attribute_names : list of strings
+        attribute_names : List[str]
             List of attribute names.
-            Only returned if return_attribute_names is True.
         """
-        if dataset_format is None:
-            warn('The default of "dataset_format" will change from "array" to'
-                 ' "dataframe" in 0.9', FutureWarning)
-            dataset_format = 'array'
-
-        rval = []
-
         if self.data_pickle_file is None:
             if self.data_file is None:
                 self._download_data()
@@ -480,23 +473,17 @@ class OpenMLDataset(object):
                 data, categorical, attribute_names = pickle.load(fh)
 
         to_exclude = []
-        if include_row_id is False:
-            if not self.row_id_attribute:
-                pass
-            else:
-                if isinstance(self.row_id_attribute, str):
-                    to_exclude.append(self.row_id_attribute)
-                else:
-                    to_exclude.extend(self.row_id_attribute)
-
-        if include_ignore_attributes is False:
-            if not self.ignore_attributes:
-                pass
-            else:
-                if isinstance(self.ignore_attributes, str):
-                    to_exclude.append(self.ignore_attributes)
-                else:
-                    to_exclude.extend(self.ignore_attributes)
+        if not include_row_id and self.row_id_attribute is not None:
+            if isinstance(self.row_id_attribute, str):
+                to_exclude.append(self.row_id_attribute)
+            elif isinstance(self.row_id_attribute, Iterable):
+                to_exclude.extend(self.row_id_attribute)
+
+        if not include_ignore_attributes and self.ignore_attributes is not None:
+            if isinstance(self.ignore_attributes, str):
+                to_exclude.append(self.ignore_attributes)
+            elif isinstance(self.ignore_attributes, Iterable):
+                to_exclude.extend(self.ignore_attributes)
 
         if len(to_exclude) > 0:
             logger.info("Going to remove the following attributes:"
@@ -514,7 +501,7 @@ class OpenMLDataset(object):
         if target is None:
             data = self._convert_array_format(data, dataset_format,
                                               attribute_names)
-            rval.append(data)
+            targets = None
         else:
             if isinstance(target, str):
                 if ',' in target:
@@ -552,19 +539,9 @@ class OpenMLDataset(object):
             y = y.squeeze()
             y = self._convert_array_format(y, dataset_format, attribute_names)
             y = y.astype(target_dtype) if dataset_format == 'array' else y
+            data, targets = x, y
 
-            rval.append(x)
-            rval.append(y)
-
-        if return_categorical_indicator:
-            rval.append(categorical)
-        if return_attribute_names:
-            rval.append(attribute_names)
-
-        if len(rval) == 1:
-            return rval[0]
-        else:
-            return rval
+        return data, targets, categorical, attribute_names
 
     def retrieve_class_labels(self, target_name: str = 'class') -> Union[None, List[str]]:
         """Reads the datasets arff to determine the class-labels.
diff --git a/openml/tasks/task.py b/openml/tasks/task.py
index e348dc39..0847189b 100644
--- a/openml/tasks/task.py
+++ b/openml/tasks/task.py
@@ -230,7 +230,10 @@ class OpenMLSupervisedTask(OpenMLTask, ABC):
     def get_X_and_y(
         self,
         dataset_format: str = 'array',
-    ) -> Union[np.ndarray, pd.DataFrame, scipy.sparse.spmatrix]:
+    ) -> Tuple[
+        Union[np.ndarray, pd.DataFrame, scipy.sparse.spmatrix],
+        Union[np.ndarray, pd.Series]
+    ]:
         """Get data associated with the current task.
 
         Parameters
@@ -247,10 +250,10 @@ class OpenMLSupervisedTask(OpenMLTask, ABC):
         dataset = self.get_dataset()
         if self.task_type_id not in (1, 2, 3):
             raise NotImplementedError(self.task_type)
-        X_and_y = dataset.get_data(
+        X, y, _, _ = dataset.get_data(
             dataset_format=dataset_format, target=self.target_name,
         )
-        return X_and_y
+        return X, y
 
     def _to_dict(self) -> 'OrderedDict[str, OrderedDict]':
 
@@ -393,10 +396,10 @@ class OpenMLClusteringTask(OpenMLTask):
 
         """
         dataset = self.get_dataset()
-        X_and_y = dataset.get_data(
+        data, *_ = dataset.get_data(
             dataset_format=dataset_format, target=None,
         )
-        return X_and_y
+        return data
 
     def _to_dict(self) -> 'OrderedDict[str, OrderedDict]':
 

openml.datasets.get_data() has unpredictable number of return values
MWE:
```
dataset = openml.datasets.get_dataset(40978)

res = dataset.get_data(target=dataset.default_target_attribute)
print(len(res))
dataset = openml.datasets.get_dataset(2)

res = dataset.get_data(target=dataset.default_target_attribute)
print(len(res))
```
This depends on whether a default target attribute has been specified. 
diff --git a/tests/test_datasets/test_dataset.py b/tests/test_datasets/test_dataset.py
index 814408ce..5f4f9806 100644
--- a/tests/test_datasets/test_dataset.py
+++ b/tests/test_datasets/test_dataset.py
@@ -27,114 +27,26 @@ class OpenMLDatasetTest(TestBase):
         self.pc4 = openml.datasets.get_dataset(1049, download_data=False)
         self.jm1 = openml.datasets.get_dataset(1053, download_data=False)
 
-    def test_get_data_future_warning(self):
-        warn_msg = 'will change from "array" to "dataframe"'
-        with pytest.warns(FutureWarning, match=warn_msg):
-            self.dataset.get_data()
-
-    def test_get_data(self):
+    def test_get_data_array(self):
         # Basic usage
-        rval = self.dataset.get_data(dataset_format='array')
+        rval, _, categorical, attribute_names = self.dataset.get_data(dataset_format='array')
         self.assertIsInstance(rval, np.ndarray)
         self.assertEqual(rval.dtype, np.float32)
         self.assertEqual((898, 39), rval.shape)
-        rval, categorical = self.dataset.get_data(
-            dataset_format='array', return_categorical_indicator=True
-        )
         self.assertEqual(len(categorical), 39)
         self.assertTrue(all([isinstance(cat, bool) for cat in categorical]))
-        rval, attribute_names = self.dataset.get_data(
-            dataset_format='array', return_attribute_names=True
-        )
         self.assertEqual(len(attribute_names), 39)
         self.assertTrue(all([isinstance(att, str)
                              for att in attribute_names]))
+        self.assertIsNone(_)
 
         # check that an error is raised when the dataset contains string
         err_msg = "PyOpenML cannot handle string when returning numpy arrays"
         with pytest.raises(PyOpenMLError, match=err_msg):
             self.titanic.get_data(dataset_format='array')
 
-    def test_get_data_with_rowid(self):
-        self.dataset.row_id_attribute = "condition"
-        rval, categorical = self.dataset.get_data(
-            dataset_format='array', include_row_id=True,
-            return_categorical_indicator=True
-        )
-        self.assertEqual(rval.dtype, np.float32)
-        self.assertEqual(rval.shape, (898, 39))
-        self.assertEqual(len(categorical), 39)
-        rval, categorical = self.dataset.get_data(
-            dataset_format='array', include_row_id=False,
-            return_categorical_indicator=True
-        )
-        self.assertEqual(rval.dtype, np.float32)
-        self.assertEqual(rval.shape, (898, 38))
-        self.assertEqual(len(categorical), 38)
-
-    def test_get_data_with_target(self):
-        X, y = self.dataset.get_data(dataset_format='array', target="class")
-        self.assertIsInstance(X, np.ndarray)
-        self.assertEqual(X.dtype, np.float32)
-        self.assertIn(y.dtype, [np.int32, np.int64])
-        self.assertEqual(X.shape, (898, 38))
-        X, y, attribute_names = self.dataset.get_data(
-            dataset_format='array',
-            target="class",
-            return_attribute_names=True
-        )
-        self.assertEqual(len(attribute_names), 38)
-        self.assertNotIn("class", attribute_names)
-        self.assertEqual(y.shape, (898, ))
-
-    def test_get_data_rowid_and_ignore_and_target(self):
-        self.dataset.ignore_attributes = ["condition"]
-        self.dataset.row_id_attribute = ["hardness"]
-        X, y = self.dataset.get_data(
-            dataset_format='array',
-            target="class",
-            include_row_id=False,
-            include_ignore_attributes=False
-        )
-        self.assertEqual(X.dtype, np.float32)
-        self.assertIn(y.dtype, [np.int32, np.int64])
-        self.assertEqual(X.shape, (898, 36))
-        X, y, categorical = self.dataset.get_data(
-            dataset_format='array',
-            target="class",
-            return_categorical_indicator=True,
-        )
-        self.assertEqual(len(categorical), 36)
-        self.assertListEqual(categorical, [True] * 3 + [False] + [True] * 2 + [
-            False] + [True] * 23 + [False] * 3 + [True] * 3)
-        self.assertEqual(y.shape, (898, ))
-
-    def test_get_data_with_ignore_attributes(self):
-        self.dataset.ignore_attributes = ["condition"]
-        rval = self.dataset.get_data(
-            dataset_format='array', include_ignore_attributes=True
-        )
-        self.assertEqual(rval.dtype, np.float32)
-        self.assertEqual(rval.shape, (898, 39))
-        rval, categorical = self.dataset.get_data(
-            dataset_format='array', include_ignore_attributes=True,
-            return_categorical_indicator=True
-        )
-        self.assertEqual(len(categorical), 39)
-        rval = self.dataset.get_data(
-            dataset_format='array', include_ignore_attributes=False
-        )
-        self.assertEqual(rval.dtype, np.float32)
-        self.assertEqual(rval.shape, (898, 38))
-        rval, categorical = self.dataset.get_data(
-            dataset_format='array', include_ignore_attributes=False,
-            return_categorical_indicator=True
-        )
-        self.assertEqual(len(categorical), 38)
-        # TODO test multiple ignore attributes!
-
     def test_get_data_pandas(self):
-        data = self.titanic.get_data(dataset_format='dataframe')
+        data, _, _, _ = self.titanic.get_data(dataset_format='dataframe')
         self.assertTrue(isinstance(data, pd.DataFrame))
         self.assertEqual(data.shape[1], len(self.titanic.features))
         self.assertEqual(data.shape[0], 1309)
@@ -157,7 +69,7 @@ class OpenMLDatasetTest(TestBase):
         for col_name in data.columns:
             self.assertTrue(data[col_name].dtype.name == col_dtype[col_name])
 
-        X, y = self.titanic.get_data(
+        X, y, _, _ = self.titanic.get_data(
             dataset_format='dataframe',
             target=self.titanic.default_target_attribute)
         self.assertTrue(isinstance(X, pd.DataFrame))
@@ -171,14 +83,88 @@ class OpenMLDatasetTest(TestBase):
     def test_get_data_boolean_pandas(self):
         # test to check that we are converting properly True and False even
         # with some inconsistency when dumping the data on openml
-        data = self.jm1.get_data(dataset_format='dataframe')
+        data, _, _, _ = self.jm1.get_data()
         self.assertTrue(data['defects'].dtype.name == 'category')
-        self.assertTrue(
-            set(data['defects'].cat.categories) == set([True, False])
-        )
-        data = self.pc4.get_data(dataset_format='dataframe')
+        self.assertTrue(set(data['defects'].cat.categories) == {True, False})
+
+        data, _, _, _ = self.pc4.get_data()
         self.assertTrue(data['c'].dtype.name == 'category')
-        self.assertTrue(set(data['c'].cat.categories) == set([True, False]))
+        self.assertTrue(set(data['c'].cat.categories) == {True, False})
+
+    def test_get_data_no_str_data_for_nparrays(self):
+        # check that an error is raised when the dataset contains string
+        err_msg = "PyOpenML cannot handle string when returning numpy arrays"
+        with pytest.raises(PyOpenMLError, match=err_msg):
+            self.titanic.get_data(dataset_format='array')
+
+    def test_get_data_with_rowid(self):
+        self.dataset.row_id_attribute = "condition"
+        rval, _, categorical, _ = self.dataset.get_data(include_row_id=True)
+        self.assertIsInstance(rval, pd.DataFrame)
+        for (dtype, is_cat) in zip(rval.dtypes, categorical):
+            expected_type = 'category' if is_cat else 'float64'
+            self.assertEqual(dtype.name, expected_type)
+        self.assertEqual(rval.shape, (898, 39))
+        self.assertEqual(len(categorical), 39)
+
+        rval, _, categorical, _ = self.dataset.get_data()
+        self.assertIsInstance(rval, pd.DataFrame)
+        for (dtype, is_cat) in zip(rval.dtypes, categorical):
+            expected_type = 'category' if is_cat else 'float64'
+            self.assertEqual(dtype.name, expected_type)
+        self.assertEqual(rval.shape, (898, 38))
+        self.assertEqual(len(categorical), 38)
+
+    def test_get_data_with_target_array(self):
+        X, y, _, attribute_names = self.dataset.get_data(dataset_format='array', target="class")
+        self.assertIsInstance(X, np.ndarray)
+        self.assertEqual(X.dtype, np.float32)
+        self.assertEqual(X.shape, (898, 38))
+        self.assertIn(y.dtype, [np.int32, np.int64])
+        self.assertEqual(y.shape, (898, ))
+        self.assertEqual(len(attribute_names), 38)
+        self.assertNotIn("class", attribute_names)
+
+    def test_get_data_with_target_pandas(self):
+        X, y, categorical, attribute_names = self.dataset.get_data(target="class")
+        self.assertIsInstance(X, pd.DataFrame)
+        for (dtype, is_cat) in zip(X.dtypes, categorical):
+            expected_type = 'category' if is_cat else 'float64'
+            self.assertEqual(dtype.name, expected_type)
+        self.assertIsInstance(y, pd.Series)
+        self.assertEqual(y.dtype.name, 'category')
+
+        self.assertEqual(X.shape, (898, 38))
+        self.assertEqual(len(attribute_names), 38)
+        self.assertEqual(y.shape, (898, ))
+
+        self.assertNotIn("class", attribute_names)
+
+    def test_get_data_rowid_and_ignore_and_target(self):
+        self.dataset.ignore_attributes = ["condition"]
+        self.dataset.row_id_attribute = ["hardness"]
+        X, y, categorical, names = self.dataset.get_data(target="class")
+        self.assertEqual(X.shape, (898, 36))
+        self.assertEqual(len(categorical), 36)
+        cats = [True] * 3 + [False, True, True, False] + [True] * 23 + [False] * 3 + [True] * 3
+        self.assertListEqual(categorical, cats)
+        self.assertEqual(y.shape, (898, ))
+
+    def test_get_data_with_ignore_attributes(self):
+        self.dataset.ignore_attributes = ["condition"]
+        rval, _, categorical, _ = self.dataset.get_data(include_ignore_attributes=True)
+        for (dtype, is_cat) in zip(rval.dtypes, categorical):
+            expected_type = 'category' if is_cat else 'float64'
+            self.assertEqual(dtype.name, expected_type)
+        self.assertEqual(rval.shape, (898, 39))
+        self.assertEqual(len(categorical), 39)
+
+        rval, _, categorical, _ = self.dataset.get_data(include_ignore_attributes=False)
+        for (dtype, is_cat) in zip(rval.dtypes, categorical):
+            expected_type = 'category' if is_cat else 'float64'
+            self.assertEqual(dtype.name, expected_type)
+        self.assertEqual(rval.shape, (898, 38))
+        self.assertEqual(len(categorical), 38)
 
     def test_dataset_format_constructor(self):
 
@@ -196,12 +182,12 @@ class OpenMLDatasetTest(TestBase):
         # This class is using the anneal dataset with labels [1, 2, 3, 4, 5, 'U']. However,
         # label 4 does not exist and we test that the features 5 and 'U' are correctly mapped to
         # indices 4 and 5, and that nothing is mapped to index 3.
-        _, y = self.dataset.get_data('class', dataset_format='dataframe')
+        _, y, _, _ = self.dataset.get_data('class', dataset_format='dataframe')
         self.assertEqual(list(y.dtype.categories), ['1', '2', '3', '4', '5', 'U'])
-        _, y = self.dataset.get_data('class', dataset_format='array')
+        _, y, _, _ = self.dataset.get_data('class', dataset_format='array')
         self.assertEqual(np.min(y), 0)
         self.assertEqual(np.max(y), 5)
-        # Check that the
+        # Check that no label is mapped to 3, since it is reserved for label '4'.
         self.assertEqual(np.sum(y == 3), 0)
 
 
@@ -234,61 +220,50 @@ class OpenMLDatasetTestSparse(TestBase):
         self.sparse_dataset = openml.datasets.get_dataset(4136, download_data=False)
 
     def test_get_sparse_dataset_with_target(self):
-        X, y = self.sparse_dataset.get_data(
+        X, y, _, attribute_names = self.sparse_dataset.get_data(
             dataset_format='array', target="class"
         )
+
         self.assertTrue(sparse.issparse(X))
         self.assertEqual(X.dtype, np.float32)
+        self.assertEqual(X.shape, (600, 20000))
+
         self.assertIsInstance(y, np.ndarray)
         self.assertIn(y.dtype, [np.int32, np.int64])
-        self.assertEqual(X.shape, (600, 20000))
-        X, y, attribute_names = self.sparse_dataset.get_data(
-            dataset_format='array',
-            target="class",
-            return_attribute_names=True,
-        )
-        self.assertTrue(sparse.issparse(X))
+        self.assertEqual(y.shape, (600, ))
+
         self.assertEqual(len(attribute_names), 20000)
         self.assertNotIn("class", attribute_names)
-        self.assertEqual(y.shape, (600, ))
 
     def test_get_sparse_dataset(self):
-        rval = self.sparse_dataset.get_data(dataset_format='array')
+        rval, _, categorical, attribute_names = self.sparse_dataset.get_data(dataset_format='array')
         self.assertTrue(sparse.issparse(rval))
         self.assertEqual(rval.dtype, np.float32)
         self.assertEqual((600, 20001), rval.shape)
-        rval, categorical = self.sparse_dataset.get_data(
-            dataset_format='array', return_categorical_indicator=True
-        )
-        self.assertTrue(sparse.issparse(rval))
+
         self.assertEqual(len(categorical), 20001)
         self.assertTrue(all([isinstance(cat, bool) for cat in categorical]))
-        rval, attribute_names = self.sparse_dataset.get_data(
-            dataset_format='array', return_attribute_names=True
-        )
-        self.assertTrue(sparse.issparse(rval))
+
         self.assertEqual(len(attribute_names), 20001)
-        self.assertTrue(all([isinstance(att, str)
-                             for att in attribute_names]))
+        self.assertTrue(all([isinstance(att, str) for att in attribute_names]))
 
     def test_get_sparse_dataframe(self):
-        rval = self.sparse_dataset.get_data(dataset_format='dataframe')
+        rval, *_ = self.sparse_dataset.get_data()
         self.assertTrue(isinstance(rval, pd.SparseDataFrame))
         self.assertEqual((600, 20001), rval.shape)
 
     def test_get_sparse_dataset_with_rowid(self):
         self.sparse_dataset.row_id_attribute = ["V256"]
-        rval, categorical = self.sparse_dataset.get_data(
-            dataset_format='array', include_row_id=True,
-            return_categorical_indicator=True
+        rval, _, categorical, _ = self.sparse_dataset.get_data(
+            dataset_format='array', include_row_id=True
         )
         self.assertTrue(sparse.issparse(rval))
         self.assertEqual(rval.dtype, np.float32)
         self.assertEqual(rval.shape, (600, 20001))
         self.assertEqual(len(categorical), 20001)
-        rval, categorical = self.sparse_dataset.get_data(
-            dataset_format='array', include_row_id=False,
-            return_categorical_indicator=True
+
+        rval, _, categorical, _ = self.sparse_dataset.get_data(
+            dataset_format='array', include_row_id=False
         )
         self.assertTrue(sparse.issparse(rval))
         self.assertEqual(rval.dtype, np.float32)
@@ -297,37 +272,27 @@ class OpenMLDatasetTestSparse(TestBase):
 
     def test_get_sparse_dataset_with_ignore_attributes(self):
         self.sparse_dataset.ignore_attributes = ["V256"]
-        rval = self.sparse_dataset.get_data(
+        rval, _, categorical, _ = self.sparse_dataset.get_data(
             dataset_format='array', include_ignore_attributes=True
         )
         self.assertTrue(sparse.issparse(rval))
         self.assertEqual(rval.dtype, np.float32)
         self.assertEqual(rval.shape, (600, 20001))
-        rval, categorical = self.sparse_dataset.get_data(
-            dataset_format='array', include_ignore_attributes=True,
-            return_categorical_indicator=True
-        )
-        self.assertTrue(sparse.issparse(rval))
+
         self.assertEqual(len(categorical), 20001)
-        rval = self.sparse_dataset.get_data(
+        rval, _, categorical, _ = self.sparse_dataset.get_data(
             dataset_format='array', include_ignore_attributes=False
         )
         self.assertTrue(sparse.issparse(rval))
         self.assertEqual(rval.dtype, np.float32)
         self.assertEqual(rval.shape, (600, 20000))
-        rval, categorical = self.sparse_dataset.get_data(
-            dataset_format='array', include_ignore_attributes=False,
-            return_categorical_indicator=True
-        )
-        self.assertTrue(sparse.issparse(rval))
         self.assertEqual(len(categorical), 20000)
-        # TODO test multiple ignore attributes!
 
     def test_get_sparse_dataset_rowid_and_ignore_and_target(self):
         # TODO: re-add row_id and ignore attributes
         self.sparse_dataset.ignore_attributes = ["V256"]
         self.sparse_dataset.row_id_attribute = ["V512"]
-        X, y = self.sparse_dataset.get_data(
+        X, y, categorical, _ = self.sparse_dataset.get_data(
             dataset_format='array',
             target="class",
             include_row_id=False,
@@ -337,12 +302,7 @@ class OpenMLDatasetTestSparse(TestBase):
         self.assertEqual(X.dtype, np.float32)
         self.assertIn(y.dtype, [np.int32, np.int64])
         self.assertEqual(X.shape, (600, 19998))
-        X, y, categorical = self.sparse_dataset.get_data(
-            dataset_format='array',
-            target="class",
-            return_categorical_indicator=True,
-        )
-        self.assertTrue(sparse.issparse(X))
+
         self.assertEqual(len(categorical), 19998)
         self.assertListEqual(categorical, [False] * 19998)
         self.assertEqual(y.shape, (600, ))
diff --git a/tests/test_datasets/test_dataset_functions.py b/tests/test_datasets/test_dataset_functions.py
index 38fcb7c5..ca60be11 100644
--- a/tests/test_datasets/test_dataset_functions.py
+++ b/tests/test_datasets/test_dataset_functions.py
@@ -385,7 +385,7 @@ class TestOpenMLDataset(TestBase):
 
     def test_get_dataset_sparse(self):
         dataset = openml.datasets.get_dataset(102, download_data=False)
-        X = dataset.get_data(dataset_format='array')
+        X, *_ = dataset.get_data(dataset_format='array')
         self.assertIsInstance(X, scipy.sparse.csr_matrix)
 
     def test_download_rowid(self):

pip install -e .[test]
parse_log_pytest
pytest
pytest
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
beautifulsoup4==4.13.3
bleach==6.0.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
cycler==0.11.0
debtcollector==2.5.0
defusedxml==0.7.1
entrypoints==0.4
execnet==2.0.2
fasteners==0.19
fastjsonschema==2.21.1
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
fonttools==4.38.0
idna==3.10
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
importlib-resources==5.12.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
iso8601==2.1.0
Jinja2==3.1.6
joblib==1.3.2
jsonschema==4.17.3
jupyter_client==7.4.9
jupyter_core==4.12.0
jupyterlab-pygments==0.2.2
kiwisolver==1.4.5
liac-arff==2.5.0
MarkupSafe==2.1.5
matplotlib==3.5.3
mistune==3.0.2
nbclient==0.7.4
nbconvert==7.6.0
nbformat==5.8.0
nest-asyncio==1.6.0
netaddr==1.3.0
netifaces==0.11.0
numpy==1.21.6
-e git+https://github.com/openml/openml-python.git@813daebea2d0c4932641f013ef79ba0ca72a9f46#egg=openml
oslo.concurrency==4.5.1
oslo.config==8.8.1
oslo.i18n==5.1.0
oslo.utils==4.13.0
packaging @ file:///croot/packaging_1671697413597/work
pandas==1.3.5
pandocfilters==1.5.1
pbr==6.1.1
Pillow==9.5.0
pkgutil_resolve_name==1.3.10
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
Pygments==2.17.2
pyparsing==3.1.4
pyrsistent==0.19.3
pytest==7.1.2
pytest-timeout==2.3.1
pytest-xdist==3.5.0
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==6.0.1
pyzmq==26.2.1
requests==2.31.0
rfc3986==2.0.0
scikit-learn==1.0.2
scipy==1.7.3
six==1.17.0
soupsieve==2.4.1
stevedore==3.5.2
threadpoolctl==3.1.0
tinycss2==1.2.1
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
tornado==6.2
traitlets==5.9.0
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
urllib3==2.0.7
webencodings==0.5.1
wrapt==1.16.0
xmltodict==0.14.2
zipp @ file:///croot/zipp_1672387121353/work

name: openml-python
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - beautifulsoup4==4.13.3
      - bleach==6.0.0
      - charset-normalizer==3.4.1
      - cycler==0.11.0
      - debtcollector==2.5.0
      - defusedxml==0.7.1
      - entrypoints==0.4
      - execnet==2.0.2
      - fasteners==0.19
      - fastjsonschema==2.21.1
      - fonttools==4.38.0
      - idna==3.10
      - importlib-resources==5.12.0
      - iso8601==2.1.0
      - jinja2==3.1.6
      - joblib==1.3.2
      - jsonschema==4.17.3
      - jupyter-client==7.4.9
      - jupyter-core==4.12.0
      - jupyterlab-pygments==0.2.2
      - kiwisolver==1.4.5
      - liac-arff==2.5.0
      - markupsafe==2.1.5
      - matplotlib==3.5.3
      - mistune==3.0.2
      - nbclient==0.7.4
      - nbconvert==7.6.0
      - nbformat==5.8.0
      - nest-asyncio==1.6.0
      - netaddr==1.3.0
      - netifaces==0.11.0
      - numpy==1.21.6
      - oslo-concurrency==4.5.1
      - oslo-config==8.8.1
      - oslo-i18n==5.1.0
      - oslo-utils==4.13.0
      - pandas==1.3.5
      - pandocfilters==1.5.1
      - pbr==6.1.1
      - pillow==9.5.0
      - pkgutil-resolve-name==1.3.10
      - pygments==2.17.2
      - pyparsing==3.1.4
      - pyrsistent==0.19.3
      - pytest-timeout==2.3.1
      - pytest-xdist==3.5.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==6.0.1
      - pyzmq==26.2.1
      - requests==2.31.0
      - rfc3986==2.0.0
      - scikit-learn==1.0.2
      - scipy==1.7.3
      - six==1.17.0
      - soupsieve==2.4.1
      - stevedore==3.5.2
      - threadpoolctl==3.1.0
      - tinycss2==1.2.1
      - tornado==6.2
      - traitlets==5.9.0
      - urllib3==2.0.7
      - webencodings==0.5.1
      - wrapt==1.16.0
      - xmltodict==0.14.2
prefix: /opt/conda/envs/openml-python

tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_array tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_boolean_pandas tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_pandas tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_rowid_and_ignore_and_target tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_with_ignore_attributes tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_with_nonexisting_class tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_with_rowid tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_with_target_array tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_with_target_pandas tests/test_datasets/test_dataset.py::OpenMLDatasetTestSparse::test_get_sparse_dataset tests/test_datasets/test_dataset.py::OpenMLDatasetTestSparse::test_get_sparse_dataset_rowid_and_ignore_and_target tests/test_datasets/test_dataset.py::OpenMLDatasetTestSparse::test_get_sparse_dataset_with_ignore_attributes tests/test_datasets/test_dataset.py::OpenMLDatasetTestSparse::test_get_sparse_dataset_with_rowid tests/test_datasets/test_dataset.py::OpenMLDatasetTestSparse::test_get_sparse_dataset_with_target
tests/test_datasets/test_dataset.py::OpenMLDatasetTestOnTestServer::test_tagging tests/test_datasets/test_dataset.py::OpenMLDatasetTestSparse::test_get_sparse_dataframe tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__name_to_id_with_multiple_active_error tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__name_to_id_with_version tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_attributes_arff_from_df tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_dataset_pandas tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_dataset_lazy_all_functions tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_tag_untag_dataset
tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_dataset_format_constructor tests/test_datasets/test_dataset.py::OpenMLDatasetTest::test_get_data_no_str_data_for_nparrays tests/test_datasets/test_dataset.py::OpenMLDatasetQualityTest::test__check_qualities tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__get_cached_dataset tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__get_cached_datasets tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__get_dataset_description tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__get_dataset_features tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__get_dataset_qualities tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__getarff_md5_issue tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__getarff_path_dataset_arff tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__list_cached_datasets tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__name_to_id_name_does_not_exist tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__name_to_id_version_does_not_exist tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__name_to_id_with_deactivated tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__name_to_id_with_multiple_active tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test__retrieve_class_labels tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_attributes_arff_from_df_mixed_dtype_categories tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_attributes_arff_from_df_unknown_dtype tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_check_datasets_active tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_dataset_attributes_auto_without_df tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_dataset_list tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_dataset_numpy tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_dataset_row_id_attribute_error tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_dataset_row_id_attribute_inference tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_dataset_sparse tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_create_invalid_dataset tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_data_status tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_deletion_of_cache_dir tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_deletion_of_cache_dir_faulty_download tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_download_rowid tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_cached_dataset_arff tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_cached_dataset_arff_not_cached tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_cached_dataset_description tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_cached_dataset_description_not_cached tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_dataset tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_dataset_by_name tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_dataset_lazy tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_dataset_sparse tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_datasets tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_datasets_by_mixed tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_datasets_by_name tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_datasets_lazy tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_online_dataset_arff tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_get_online_dataset_format tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_ignore_attributes_dataset tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_by_number_classes tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_by_number_features tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_by_number_instances tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_by_number_missing_values tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_by_size tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_by_tag tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_combined_filters tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_empty tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_list_datasets_paginate tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_publish_dataset tests/test_datasets/test_dataset_functions.py::TestOpenMLDataset::test_upload_dataset_with_url
openml/tasks/task.py examples/datasets_tutorial.py openml/datasets/dataset.py examples/flows_and_runs_tutorial.py
openml/tasks/task.py examples/datasets_tutorial.py openml/datasets/dataset.py examples/flows_and_runs_tutorial.py