diff --git a/howso/client/pandas/client.py b/howso/client/pandas/client.py index aa0d1ba5..30b80b2e 100644 --- a/howso/client/pandas/client.py +++ b/howso/client/pandas/client.py @@ -229,7 +229,7 @@ def react_series( """ trainee_id = self._resolve_trainee_id(trainee_id) feature_attributes = self.trainee_cache.get(trainee_id).features - response = super().react_series(trainee_id, series_index, *args, **kwargs) + response = super().react_series(trainee_id, *args, series_index=series_index, **kwargs) response['series'] = format_dataframe(response.get("series"), feature_attributes) diff --git a/howso/client/tests/test_client.py b/howso/client/tests/test_client.py index ca245cfe..25a367a6 100644 --- a/howso/client/tests/test_client.py +++ b/howso/client/tests/test_client.py @@ -30,6 +30,7 @@ Trainee, TrainResponse, ) +from howso.utilities.reaction import CasesWithDetails from howso.utilities.testing import get_configurationless_test_client, get_test_options import numpy as np import pandas as pd @@ -312,6 +313,7 @@ def test_react(self, trainee): features=df.columns.tolist()) response = self.client.react(trainee.id, contexts=[["2020-10-12T10:10:10.333"]]) + assert isinstance(response, CasesWithDetails) assert response['action']['nom'].iloc[0] == "b" response = self.client.react(trainee.id, contexts=[["b"]], @@ -319,6 +321,20 @@ def test_react(self, trainee): action_features=["datetime"]) assert "2020-10-12T10:10:10.333000" in response['action']['datetime'].iloc[0] + def test_react_series(self, trainee): + """Test that react series works as expected.""" + df = pd.DataFrame(data=np.asarray([ + ['a', 'b', 'c', 'd'], + ['2020-9-12T9:09:09.123', '2020-10-12T10:10:10.333', + '2020-12-12T12:12:12.444', '2020-10-11T11:11:11.222'] + ]).transpose(), columns=['nom', 'datetime']) + self.client.train(trainee.id, cases=df.values.tolist(), + features=df.columns.tolist()) + response = self.client.react_series(trainee.id, + contexts=[["2020-10-12T10:10:10.333"]]) + assert isinstance(response, CasesWithDetails) + assert response['action']['nom'].iloc[0] == "b" + class TestClient: """Define a Client test class.""" @@ -424,6 +440,7 @@ def test_train_and_react(self, trainee): cases = [['1', '2'], ['3', '4']] self.client.train(trainee.id, cases, features=['penguin', 'play']) react_response = self.client.react(trainee.id, contexts=[['1']]) + assert isinstance(react_response, CasesWithDetails) assert react_response['action']['play'].iloc[0] == '2' case_response = self.client.get_cases( trainee.id, session=self.client.active_session.id) diff --git a/howso/utilities/reaction.py b/howso/utilities/reaction.py index 6175f3f0..595fc243 100644 --- a/howso/utilities/reaction.py +++ b/howso/utilities/reaction.py @@ -210,12 +210,6 @@ def _(self, action: list, details: t.MutableMapping[str, t.Any]): action_df = pd.DataFrame(action) return self.add_reaction(action_df, details) - @add_reaction.register - def _(self, reaction: dict): - """Add a Reaction to CasesWithDetails.""" - details = reaction.get("details", reaction.get("explanation")) - return self.add_reaction(reaction["action"], details) - def gen_cases(self) -> t.Generator[t.Dict, None, None]: """ Yield dict containing DetailedCase items for a single case. @@ -296,3 +290,9 @@ def _reorganize_details(cls, details: t.MutableMapping[str, t.List] case.update({key: details[key] for key in cls.SPECIAL_KEYS}) return per_case_details + + +@CasesWithDetails.add_reaction.register +def _(self, reaction: "CasesWithDetails"): + """Add anothoer `CasesWithDetails` to CasesWithDetails.""" + return self.add_reaction(reaction.get("action"), reaction.get("explanation", {})) diff --git a/howso/utilities/tests/test_utilities.py b/howso/utilities/tests/test_utilities.py index be298a0f..5464145d 100644 --- a/howso/utilities/tests/test_utilities.py +++ b/howso/utilities/tests/test_utilities.py @@ -7,6 +7,8 @@ from dateutil import parser import howso.utilities as utils from howso.utilities import get_kwargs, LocaleOverride +from howso.utilities.reaction import CasesWithDetails +import numpy as np import pandas as pd import pytest @@ -293,3 +295,49 @@ def test_determine_iso_format(date_str, format_str): with warnings.catch_warnings(): warnings.simplefilter("error") assert format_str == utils.determine_iso_format(date_str, "_") + + +def test_cases_with_details_add_reaction(): + """Tests that `CasesWithDetails` `add_reaction` works with different data types.""" + df = pd.DataFrame(data=np.asarray([ + ['a', 'b', 'c', 'd'], + ['2020-9-12T9:09:09.123', '2020-10-12T10:10:10.333', + '2020-12-12T12:12:12.444', '2020-10-11T11:11:11.222'] + ]).transpose(), columns=['nom', 'datetime']) + + react_response = { + 'explanation': {'action_features': ['datetime']}, + 'action': df + } + + cwd = CasesWithDetails() + cwd.add_reaction(react_response['action'], react_response['explanation']) + cwd.add_reaction(react_response['action'].to_dict(), react_response['explanation']) + # List of dicts + cwd.add_reaction(react_response['action'].to_dict(orient='records'), react_response['explanation']) + cwd.add_reaction(CasesWithDetails(react_response['action'], react_response['explanation'])) + + assert cwd['action'].shape[0] == 16 + + +def test_cases_with_details_instantiate(): + """Tests that `CasesWithDetails` can be instantiated with different data types.""" + df = pd.DataFrame(data=np.asarray([ + ['a', 'b', 'c', 'd'], + ['2020-9-12T9:09:09.123', '2020-10-12T10:10:10.333', + '2020-12-12T12:12:12.444', '2020-10-11T11:11:11.222'] + ]).transpose(), columns=['nom', 'datetime']) + + react_response = { + 'explanation': {'action_features': ['datetime']}, + 'action': df + } + + cwd = CasesWithDetails(react_response['action'], react_response['explanation']) + assert cwd['action'].shape[0] == 4 + + cwd = CasesWithDetails(react_response['action'].to_dict(), react_response['explanation']) + assert cwd['action'].shape[0] == 4 + + cwd = CasesWithDetails(react_response['action'].to_dict(orient='records'), react_response['explanation']) + assert cwd['action'].shape[0] == 4