From 818e9c49a54b8dadb903adb8ff229c8b027cc471 Mon Sep 17 00:00:00 2001 From: R-Palazzo Date: Thu, 12 Oct 2023 14:44:48 +0200 Subject: [PATCH 1/5] def --- sdmetrics/reports/base_report.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sdmetrics/reports/base_report.py b/sdmetrics/reports/base_report.py index 1f67d009..21b33e32 100644 --- a/sdmetrics/reports/base_report.py +++ b/sdmetrics/reports/base_report.py @@ -55,14 +55,25 @@ def validate(self, real_data, synthetic_data, metadata): metadata (dict): The metadata of the table. """ - if not isinstance(metadata, dict): - metadata = metadata.to_dict() - self._validate_metadata_matches_data(real_data, synthetic_data, metadata) def _handle_results(self, verbose): raise NotImplementedError + @staticmethod + def _convert_metadata(metadata): + """If the metadta is not a dict, try to convert it.""" + if not isinstance(metadata, dict): + try: + metadata = metadata.to_dict() + except Exception: + raise TypeError( + 'The provided metadata is not a dictionary and does not have a to_dict method.' + 'Please convert the metadata to a dictionary.' + ) + + return metadata + @staticmethod def convert_datetimes(real_data, synthetic_data, metadata): """Try to convert all datetime columns to datetime dtype. @@ -101,6 +112,7 @@ def generate(self, real_data, synthetic_data, metadata, verbose=True): verbose (bool): Whether or not to print report summary and progress. """ + metadata = self._convert_metadata(metadata) self.validate(real_data, synthetic_data, metadata) self.convert_datetimes(real_data, synthetic_data, metadata) From 873a4b70014f584cedb490b739857ced20137cb4 Mon Sep 17 00:00:00 2001 From: R-Palazzo Date: Thu, 12 Oct 2023 14:44:56 +0200 Subject: [PATCH 2/5] tests --- tests/unit/reports/test_base_report.py | 48 ++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tests/unit/reports/test_base_report.py b/tests/unit/reports/test_base_report.py index 90275f07..daf424e4 100644 --- a/tests/unit/reports/test_base_report.py +++ b/tests/unit/reports/test_base_report.py @@ -253,6 +253,54 @@ def test_generate_verbose(self, mock_tqdm): mock_tqdm.assert_has_calls(calls, any_order=True) base_report._handle_results.assert_called_once_with(True) + def test__convert_metadata_with_to_dict_method(self): + """Test ``_convert_metadata`` when the metadata object has a ``to_dict`` method.""" + # Setup + metadata_example = { + 'column1': {'sdtype': 'numerical'}, + 'column2': {'sdtype': 'categorical'}, + } + + class Metadata: + def __init__(self): + self.columns = metadata_example + + def to_dict(self): + return self.columns + + metadata = Metadata() + + # Run + converted_metadata = BaseReport._convert_metadata(metadata) + + # Assert + assert converted_metadata == metadata_example + + def test__convert_metadata_without_to_dict_method(self): + """Test ``_convert_metadata`` when the metadata object has no ``to_dict`` method.""" + # Setup + metadata_example = { + 'column1': {'sdtype': 'numerical'}, + 'column2': {'sdtype': 'categorical'}, + } + + class Metadata: + def __init__(self): + self.columns = metadata_example + + metadata = Metadata() + + # Run and Assert + expected_message = re.escape( + 'The provided metadata is not a dictionary and does not have a to_dict method.' + 'Please convert the metadata to a dictionary.' + ) + with pytest.raises(TypeError, match=expected_message): + BaseReport._convert_metadata(metadata) + + result = BaseReport._convert_metadata(metadata_example) + assert result == metadata_example + def test__check_report_generated(self): """Test the ``check_report_generated`` method.""" # Setup From a6ca725696b999a4c5e454b131a5564d4edc5b68 Mon Sep 17 00:00:00 2001 From: R-Palazzo Date: Thu, 12 Oct 2023 15:56:51 +0200 Subject: [PATCH 3/5] mock in tests --- tests/unit/reports/test_base_report.py | 101 +++++++++++++------------ 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/tests/unit/reports/test_base_report.py b/tests/unit/reports/test_base_report.py index daf424e4..1d5cfba8 100644 --- a/tests/unit/reports/test_base_report.py +++ b/tests/unit/reports/test_base_report.py @@ -152,7 +152,56 @@ def test_convert_datetimes(self): pd.testing.assert_frame_equal(real_data, expected_real_data) pd.testing.assert_frame_equal(synthetic_data, expected_synthetic_data) - def test_generate(self): + def test__convert_metadata_with_to_dict_method(self): + """Test ``_convert_metadata`` when the metadata object has a ``to_dict`` method.""" + # Setup + metadata_example = { + 'column1': {'sdtype': 'numerical'}, + 'column2': {'sdtype': 'categorical'}, + } + + class Metadata: + def __init__(self): + self.columns = metadata_example + + def to_dict(self): + return self.columns + + metadata = Metadata() + + # Run + converted_metadata = BaseReport._convert_metadata(metadata) + + # Assert + assert converted_metadata == metadata_example + + def test__convert_metadata_without_to_dict_method(self): + """Test ``_convert_metadata`` when the metadata object has no ``to_dict`` method.""" + # Setup + metadata_example = { + 'column1': {'sdtype': 'numerical'}, + 'column2': {'sdtype': 'categorical'}, + } + + class Metadata: + def __init__(self): + self.columns = metadata_example + + metadata = Metadata() + + # Run and Assert + expected_message = re.escape( + 'The provided metadata is not a dictionary and does not have a to_dict method.' + 'Please convert the metadata to a dictionary.' + ) + with pytest.raises(TypeError, match=expected_message): + BaseReport._convert_metadata(metadata) + + result = BaseReport._convert_metadata(metadata_example) + assert result == metadata_example + + @patch('sdmetrics.reports.base_report.BaseReport._convert_metadata') + def test_generate(self, mock__convert_metadata): """Test the ``generate`` method. This test checks that the method calls the ``validate`` method and the ``get_score`` @@ -183,11 +232,13 @@ def test_generate(self): 'column2': {'sdtype': 'categorical'} } } + mock__convert_metadata.return_value = metadata # Run base_report.generate(real_data, synthetic_data, metadata, verbose=False) # Assert + mock__convert_metadata.assert_called_once_with(metadata) mock_validate.assert_called_once_with(real_data, synthetic_data, metadata) mock_handle_results.assert_called_once_with(False) base_report._properties['Property 1'].get_score.assert_called_with( @@ -253,54 +304,6 @@ def test_generate_verbose(self, mock_tqdm): mock_tqdm.assert_has_calls(calls, any_order=True) base_report._handle_results.assert_called_once_with(True) - def test__convert_metadata_with_to_dict_method(self): - """Test ``_convert_metadata`` when the metadata object has a ``to_dict`` method.""" - # Setup - metadata_example = { - 'column1': {'sdtype': 'numerical'}, - 'column2': {'sdtype': 'categorical'}, - } - - class Metadata: - def __init__(self): - self.columns = metadata_example - - def to_dict(self): - return self.columns - - metadata = Metadata() - - # Run - converted_metadata = BaseReport._convert_metadata(metadata) - - # Assert - assert converted_metadata == metadata_example - - def test__convert_metadata_without_to_dict_method(self): - """Test ``_convert_metadata`` when the metadata object has no ``to_dict`` method.""" - # Setup - metadata_example = { - 'column1': {'sdtype': 'numerical'}, - 'column2': {'sdtype': 'categorical'}, - } - - class Metadata: - def __init__(self): - self.columns = metadata_example - - metadata = Metadata() - - # Run and Assert - expected_message = re.escape( - 'The provided metadata is not a dictionary and does not have a to_dict method.' - 'Please convert the metadata to a dictionary.' - ) - with pytest.raises(TypeError, match=expected_message): - BaseReport._convert_metadata(metadata) - - result = BaseReport._convert_metadata(metadata_example) - assert result == metadata_example - def test__check_report_generated(self): """Test the ``check_report_generated`` method.""" # Setup From 18d6e41575e43450be6ad133664cb1bc69d1d245 Mon Sep 17 00:00:00 2001 From: R-Palazzo Date: Thu, 12 Oct 2023 18:59:08 +0200 Subject: [PATCH 4/5] remove _convert_metadata + new message --- sdmetrics/reports/base_report.py | 18 ++------ tests/unit/reports/test_base_report.py | 60 +++++++------------------- 2 files changed, 18 insertions(+), 60 deletions(-) diff --git a/sdmetrics/reports/base_report.py b/sdmetrics/reports/base_report.py index 21b33e32..3536b3e0 100644 --- a/sdmetrics/reports/base_report.py +++ b/sdmetrics/reports/base_report.py @@ -60,20 +60,6 @@ def validate(self, real_data, synthetic_data, metadata): def _handle_results(self, verbose): raise NotImplementedError - @staticmethod - def _convert_metadata(metadata): - """If the metadta is not a dict, try to convert it.""" - if not isinstance(metadata, dict): - try: - metadata = metadata.to_dict() - except Exception: - raise TypeError( - 'The provided metadata is not a dictionary and does not have a to_dict method.' - 'Please convert the metadata to a dictionary.' - ) - - return metadata - @staticmethod def convert_datetimes(real_data, synthetic_data, metadata): """Try to convert all datetime columns to datetime dtype. @@ -112,7 +98,9 @@ def generate(self, real_data, synthetic_data, metadata, verbose=True): verbose (bool): Whether or not to print report summary and progress. """ - metadata = self._convert_metadata(metadata) + if not isinstance(metadata, dict): + raise TypeError('The provided metadata is not a dictionary.') + self.validate(real_data, synthetic_data, metadata) self.convert_datetimes(real_data, synthetic_data, metadata) diff --git a/tests/unit/reports/test_base_report.py b/tests/unit/reports/test_base_report.py index 1d5cfba8..a0cc234a 100644 --- a/tests/unit/reports/test_base_report.py +++ b/tests/unit/reports/test_base_report.py @@ -152,55 +152,27 @@ def test_convert_datetimes(self): pd.testing.assert_frame_equal(real_data, expected_real_data) pd.testing.assert_frame_equal(synthetic_data, expected_synthetic_data) - def test__convert_metadata_with_to_dict_method(self): - """Test ``_convert_metadata`` when the metadata object has a ``to_dict`` method.""" + def test_generate_metadata_not_dict(self): + """Test the ``generate`` method with metadata not being a dict.""" # Setup - metadata_example = { - 'column1': {'sdtype': 'numerical'}, - 'column2': {'sdtype': 'categorical'}, - } - - class Metadata: - def __init__(self): - self.columns = metadata_example - - def to_dict(self): - return self.columns - - metadata = Metadata() - - # Run - converted_metadata = BaseReport._convert_metadata(metadata) - - # Assert - assert converted_metadata == metadata_example - - def test__convert_metadata_without_to_dict_method(self): - """Test ``_convert_metadata`` when the metadata object has no ``to_dict`` method.""" - # Setup - metadata_example = { - 'column1': {'sdtype': 'numerical'}, - 'column2': {'sdtype': 'categorical'}, - } - - class Metadata: - def __init__(self): - self.columns = metadata_example - - metadata = Metadata() + base_report = BaseReport() + real_data = pd.DataFrame({ + 'column1': [1, 2, 3], + 'column2': ['a', 'b', 'c'] + }) + synthetic_data = pd.DataFrame({ + 'column1': [1, 2, 3], + 'column2': ['a', 'b', 'c'] + }) + metadata = 'metadata' # Run and Assert - expected_message = re.escape( - 'The provided metadata is not a dictionary and does not have a to_dict method.' - 'Please convert the metadata to a dictionary.' + expected_message = ( + 'The provided metadata is not a dictionary.' ) with pytest.raises(TypeError, match=expected_message): - BaseReport._convert_metadata(metadata) - - result = BaseReport._convert_metadata(metadata_example) - assert result == metadata_example + base_report.generate(real_data, synthetic_data, metadata, verbose=False) - @patch('sdmetrics.reports.base_report.BaseReport._convert_metadata') def test_generate(self, mock__convert_metadata): """Test the ``generate`` method. @@ -232,13 +204,11 @@ def test_generate(self, mock__convert_metadata): 'column2': {'sdtype': 'categorical'} } } - mock__convert_metadata.return_value = metadata # Run base_report.generate(real_data, synthetic_data, metadata, verbose=False) # Assert - mock__convert_metadata.assert_called_once_with(metadata) mock_validate.assert_called_once_with(real_data, synthetic_data, metadata) mock_handle_results.assert_called_once_with(False) base_report._properties['Property 1'].get_score.assert_called_with( From cc6a105bd820e609e24b7d16b352dbae4b28424e Mon Sep 17 00:00:00 2001 From: R-Palazzo Date: Thu, 12 Oct 2023 19:06:13 +0200 Subject: [PATCH 5/5] remove mock --- tests/unit/reports/test_base_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/reports/test_base_report.py b/tests/unit/reports/test_base_report.py index a0cc234a..156b096a 100644 --- a/tests/unit/reports/test_base_report.py +++ b/tests/unit/reports/test_base_report.py @@ -173,7 +173,7 @@ def test_generate_metadata_not_dict(self): with pytest.raises(TypeError, match=expected_message): base_report.generate(real_data, synthetic_data, metadata, verbose=False) - def test_generate(self, mock__convert_metadata): + def test_generate(self): """Test the ``generate`` method. This test checks that the method calls the ``validate`` method and the ``get_score``