Repository: mindsdb/mindsdb

Issue:
predict_datasource API endpoint returns `500 b'{"message": "ValueError: \'class\' is not in list"}\n'`
**Your Environment**

* 3.7.6:
* Pip version: 19.2.3
* Operating system: macOS 10.15.7
* Python environment used (e.g. venv, conda):
* Mindsdb version you tried to install: 2.13.8(staging)
* Additional info if applicable:

**Describe the bug**
predict_datasource API endpoint returns `500 b'{"message": "ValueError: \'class\' is not in list"}\n'`

**To Reproduce**
1. Launch mindsdb backend: `python -m mindsdb`
2. Download any valid datasource (you may download through API too):
     - MindsDB UI -> Data -> Upload
     - Specify datasource name (let it be TEST_DATASOURCE)

3. Create new model and train it:
     - MindsDB UI -> Predictors -> TRAIN NEW
     - Specify datasource, predictor name (let it be TEST_PREDICTOR), and column to predict
4. When predictor is ready call `predict_datasource` endpoint by using next code for as template:
```
import requests

url = "http://0.0.0.0:47334/api/predictors/TEST_PREDICTOR/predict_datasource"

payload = {'data_source_name': 'TEST_DATASOURCE'}
response = requests.request("POST", url, json=payload)
print(response.status_code, response.text.encode('utf8'))
```

**Expected behavior**
Predictions must be returned

**Actual behaviour**
`500 b'{"message": "ValueError: \'class\' is not in list"}\n'` in response

**Additional context**
Small research shows that by some reasons DataExtractor in mindsdb_native call `_data_from_when` in this case
But if use native predictor directly, DataExtractor calls `_data_from_when_data` 

There is also part of backend traceback:

```
  File "/Users/itsyplen/repos/MindsDB/mindsdb_native/mindsdb_native/libs/phases/data_extractor/data_extractor.py", line 177, in run
    def run(self):
  File "/Users/itsyplen/repos/MindsDB/mindsdb_native/mindsdb_native/libs/phases/data_extractor/data_extractor.py", line 94, in _get_prepared_input_df
    else:
  File "/Users/itsyplen/repos/MindsDB/mindsdb_native/mindsdb_native/libs/phases/data_extractor/data_extractor.py", line 34, in _data_from_when
    for condition_col in when_condition:
ValueError: 'class' is not in list
```


Discussion:

Resolving patch:
diff --git a/mindsdb/api/http/namespaces/predictor.py b/mindsdb/api/http/namespaces/predictor.py
--- a/mindsdb/api/http/namespaces/predictor.py
+++ b/mindsdb/api/http/namespaces/predictor.py
@@ -266,28 +266,27 @@ class PredictorPredictFromDataSource(Resource):
     def post(self, name):
         data = request.json
 
-        from_data = ca.default_store.get_datasource_obj(data.get('data_source_name'), raw=True)
+        from_data = ca.default_store.get_datasource_obj(data.get('data_source_name'))
         if from_data is None:
             abort(400, 'No valid datasource given')
 
         try:
             format_flag = data.get('format_flag')
-        except:
+        except Exception:
             format_flag = 'explain'
 
         try:
             kwargs = data.get('kwargs')
-        except:
+        except Exception:
             kwargs = {}
 
-        if type(kwargs) != type({}):
+        if not isinstance(kwargs, dict):
             kwargs = {}
 
         if is_custom(name):
             return ca.custom_models.predict(name, from_data=from_data, **kwargs)
-        else:
-            results = ca.mindsdb_native.predict(name, when_data=from_data, **kwargs)
 
+        results = ca.mindsdb_native.predict(name, when_data=from_data, **kwargs)
         return preparse_results(results, format_flag)
 
 
diff --git a/mindsdb/interfaces/custom/custom_models.py b/mindsdb/interfaces/custom/custom_models.py
--- a/mindsdb/interfaces/custom/custom_models.py
+++ b/mindsdb/interfaces/custom/custom_models.py
@@ -82,9 +82,16 @@ def learn(self, name, from_data, to_predict, kwargs={}):
         self.dbw.unregister_predictor(name)
         self.dbw.register_predictors([self.get_model_data(name)], setup=False)
 
-    def predict(self, name, when_data=None, from_data=None, kwargs={}):
+    def predict(self, name, when_data=None, from_data=None, kwargs=None):
+        if kwargs is None:
+            kwargs = {}
         if from_data is not None:
-            data_source = getattr(mindsdb_native, from_data['class'])(*from_data['args'], **from_data['kwargs'])
+            if isinstance(from_data, dict):
+                data_source = getattr(mindsdb_native, from_data['class'])(*from_data['args'],
+                                                                          **from_data['kwargs'])
+            # assume that particular instance of any DataSource class is provided
+            else:
+                data_source = from_data
             data_frame = data_source.df
         elif when_data is not None:
             if isinstance(when_data, dict):


Test patch: