Repository: HK3-Lab-Team/pytrousse

Issue:
Add __str__ method for FillNA

Discussion:

Patch:
diff --git a/README.md b/README.md
index 01f5eb7..3c181e0 100644
--- a/README.md
+++ b/README.md
@@ -37,18 +37,15 @@ The traced data path can be inspected through `operation_history` attribute.
 >>> dataset.operations_history
 ```
 ```bash
-[
-    FillNA(
-        columns=["column_with_nan"],
-        derived_columns=["column_filled"],
-        value=0,
-    ),
-    ReplaceSubstrings(
-        columns=["column_invalid_values"],
-        derived_columns=["column_valid_values"],
-        replacement_map={",": ".", "°": ""},
-    ),
-]
+[FillNA(
+    columns=["column_with_nan"],
+    value=0,
+    derived_columns=["column_filled"],
+), ReplaceSubstrings(
+    columns=["column_invalid_values"],
+    replacement_map={",": ".", "°": ""},
+    derived_columns=["column_valid_values"],
+)]
 ```
 
 ### Automatic column data type detection
@@ -93,13 +90,13 @@ Along with the common preprocessing utilities (for encoding, binning, scaling, e
 ...     [
 ...         FillNA(
 ...             columns=["column_with_nan"],
-...             derived_columns=["column_filled"],
 ...             value=0,
+...             derived_columns=["column_filled"],
 ...         ),
 ...         ReplaceSubstrings(
 ...             columns=["column_invalid_values"],
-...             derived_columns=["column_valid_values"],
 ...             replacement_map={",": ".", "°": ""},
+...             derived_columns=["column_valid_values"],
 ...         ),
 ...     ]
 ... )
diff --git a/src/trousse/feature_operations.py b/src/trousse/feature_operations.py
index 75bf5ca..e19380c 100644
--- a/src/trousse/feature_operations.py
+++ b/src/trousse/feature_operations.py
@@ -187,6 +187,20 @@ class FillNA(FeatureOperation):
 
         return False
 
+    def __repr__(self) -> str:
+        return (
+            self.__class__.__name__ + f"(\n\tcolumns={self.columns},"
+            f"\n\tvalue={self.value},"
+            f"\n\tderived_columns={self.derived_columns},\n)"
+        )
+
+    def __str__(self) -> str:
+        return (
+            self.__class__.__name__ + f"(\n\tcolumns={self.columns},"
+            f"\n\tvalue={self.value},"
+            f"\n\tderived_columns={self.derived_columns},\n)"
+        )
+
     def is_similar(self, other: FeatureOperation):
         raise NotImplementedError
 
@@ -318,6 +332,20 @@ class ReplaceSubstrings(FeatureOperation):
 
         return False
 
+    def __repr__(self) -> str:
+        return (
+            self.__class__.__name__ + f"(\n\tcolumns={self.columns},"
+            f"\n\treplacement_map={self.replacement_map},"
+            f"\n\tderived_columns={self.derived_columns},\n)"
+        )
+
+    def __str__(self) -> str:
+        return (
+            self.__class__.__name__ + f"(\n\tcolumns={self.columns},"
+            f"\n\treplacement_map={self.replacement_map},"
+            f"\n\tderived_columns={self.derived_columns},\n)"
+        )
+
     def is_similar(self, other: FeatureOperation):
         raise NotImplementedError
 
@@ -414,3 +442,17 @@ class ReplaceStrings(ReplaceSubstrings):
             return True
 
         return False
+
+    def __repr__(self) -> str:
+        return (
+            self.__class__.__name__ + f"(\n\tcolumns={self.columns},"
+            f"\n\treplacement_map={self.replacement_map},"
+            f"\n\tderived_columns={self.derived_columns},\n)"
+        )
+
+    def __str__(self) -> str:
+        return (
+            self.__class__.__name__ + f"(\n\tcolumns={self.columns},"
+            f"\n\treplacement_map={self.replacement_map},"
+            f"\n\tderived_columns={self.derived_columns},\n)"
+        )
diff --git a/src/trousse/operations_list.py b/src/trousse/operations_list.py
index 1df19cb..3bec9c6 100644
--- a/src/trousse/operations_list.py
+++ b/src/trousse/operations_list.py
@@ -182,3 +182,9 @@ class OperationsList:
 
     def __len__(self):
         return len(self._operations_list)
+
+    def __repr__(self) -> str:
+        return str(self._operations_list)
+
+    def __str__(self) -> str:
+        return str(self._operations_list)


Test patch:
diff --git a/tests/unit/test_feature_operations.py b/tests/unit/test_feature_operations.py
index 237c90d..2a85462 100644
--- a/tests/unit/test_feature_operations.py
+++ b/tests/unit/test_feature_operations.py
@@ -197,6 +197,16 @@ class DescribeFillNa:
         assert type(equal) == bool
         assert equal == expected_equal
 
+    def it_knows_its_str(self):
+        feat_op = fop.FillNA(columns=["col0"], derived_columns=["col1"], value=0)
+
+        _str = str(feat_op)
+
+        assert type(_str) == str
+        assert _str == (
+            "FillNA(\n\tcolumns=['col0'],\n\tvalue=0,\n\tderived_columns=['col1'],\n)"
+        )
+
 
 class DescribeReplaceStrings:
     def it_construct_from_args(self, request):
@@ -358,6 +368,21 @@ class DescribeReplaceStrings:
         assert type(equal) == bool
         assert equal == expected_equal
 
+    def it_knows_its_str(self):
+        feat_op = fop.ReplaceStrings(
+            columns=["exam_num_col_0"],
+            derived_columns=["replaced_exam_num_col_0"],
+            replacement_map={"a": "b", "c": "d"},
+        )
+
+        _str = str(feat_op)
+
+        assert type(_str) == str
+        assert _str == (
+            "ReplaceStrings(\n\tcolumns=['exam_num_col_0'],\n\treplacement_map="
+            "{'a': 'b', 'c': 'd'},\n\tderived_columns=['replaced_exam_num_col_0'],\n)"
+        )
+
 
 class DescribeReplaceSubstrings:
     def it_construct_from_args(self, request):
@@ -537,3 +562,18 @@ class DescribeReplaceSubstrings:
 
         assert type(equal) == bool
         assert equal == expected_equal
+
+    def it_knows_its_str(self):
+        feat_op = fop.ReplaceSubstrings(
+            columns=["exam_num_col_0"],
+            derived_columns=["replaced_exam_num_col_0"],
+            replacement_map={"a": "b", "c": "d"},
+        )
+
+        _str = str(feat_op)
+
+        assert type(_str) == str
+        assert _str == (
+            "ReplaceSubstrings(\n\tcolumns=['exam_num_col_0'],\n\treplacement_map="
+            "{'a': 'b', 'c': 'd'},\n\tderived_columns=['replaced_exam_num_col_0'],\n)"
+        )
diff --git a/tests/unit/test_operations_list.py b/tests/unit/test_operations_list.py
index 23eac9d..925b440 100644
--- a/tests/unit/test_operations_list.py
+++ b/tests/unit/test_operations_list.py
@@ -260,3 +260,15 @@ class DescribeOperationsList:
 
         assert type(equal) == bool
         assert equal is False
+
+    def it_knows_its_str(self, fillna_col0_col1, fillna_col1_col4):
+        op_list = OperationsList()
+        op_list._operations_list = [fillna_col0_col1, fillna_col1_col4]
+
+        _str = str(op_list)
+
+        assert type(_str) == str
+        assert _str == (
+            "[FillNA(\n\tcolumns=['col0'],\n\tvalue=0,\n\tderived_columns=['col1'],\n)"
+            ", FillNA(\n\tcolumns=['col1'],\n\tvalue=0,\n\tderived_columns=['col4'],\n)]"
+        )