Repository: great-expectations/great_expectations

Issue:
Use cleaner solution for non-truncating division in python 2
Prefer `from __future__ import division` to `1.*x/y`


Discussion:
Done inline during improve_partitions push.

Resolving patch:
diff --git a/great_expectations/core/expectation_suite.py b/great_expectations/core/expectation_suite.py
--- a/great_expectations/core/expectation_suite.py
+++ b/great_expectations/core/expectation_suite.py
@@ -89,6 +89,7 @@ def add_citation(
         batch_kwargs: Optional[dict] = None,
         batch_markers: Optional[dict] = None,
         batch_parameters: Optional[dict] = None,
+        profiler_config: Optional[dict] = None,
         citation_date: Optional[Union[str, datetime.datetime]] = None,
     ):
         if "citations" not in self.meta:
@@ -109,6 +110,7 @@ def add_citation(
                 "batch_kwargs": batch_kwargs,
                 "batch_markers": batch_markers,
                 "batch_parameters": batch_parameters,
+                "profiler_config": profiler_config,
                 "comment": comment,
             }
         )
@@ -195,6 +197,7 @@ def get_citations(
         sort: Optional[bool] = True,
         require_batch_kwargs: Optional[bool] = False,
         require_batch_request: Optional[bool] = False,
+        require_profiler_config: Optional[bool] = False,
     ) -> List[Dict[str, Any]]:
         citations: List[Dict[str, Any]] = self.meta.get("citations", [])
         if require_batch_kwargs:
@@ -205,6 +208,10 @@ def get_citations(
             citations = self._filter_citations(
                 citations=citations, filter_key="batch_request"
             )
+        if require_profiler_config:
+            citations = self._filter_citations(
+                citations=citations, filter_key="profiler_config"
+            )
         if not sort:
             return citations
         return self._sort_citations(citations=citations)


Test patch:
diff --git a/tests/core/test_expectation_suite.py b/tests/core/test_expectation_suite.py
--- a/tests/core/test_expectation_suite.py
+++ b/tests/core/test_expectation_suite.py
@@ -3,6 +3,7 @@
 from typing import Any, Dict, List
 
 import pytest
+from ruamel.yaml import YAML
 
 from great_expectations.core.expectation_configuration import ExpectationConfiguration
 from great_expectations.core.expectation_suite import ExpectationSuite
@@ -168,6 +169,50 @@ def different_suite(exp1, exp4):
     )
 
 
+@pytest.fixture
+def profiler_config():
+    # Profiler configuration is pulled from the Bobster use case in tests/rule_based_profiler/
+    yaml_config = """
+    # This profiler is meant to be used on the NYC taxi data:
+    # tests/test_sets/taxi_yellow_trip_data_samples/yellow_trip_data_sample_20(18|19|20)-*.csv
+    variables:
+      # BatchRequest yielding thirty five (35) batches (January, 2018 -- November, 2020 trip data)
+      jan_2018_thru_nov_2020_monthly_trip_data_batch_request:
+        datasource_name: taxi_pandas
+        data_connector_name: monthly
+        data_asset_name: my_reports
+        data_connector_query:
+          index: ":-1"
+      confidence_level: 9.5e-1
+      mostly: 1.0
+
+    rules:
+      row_count_range_rule:
+        domain_builder:
+          class_name: TableDomainBuilder
+        parameter_builders:
+          - parameter_name: row_count_range
+            class_name: NumericMetricRangeMultiBatchParameterBuilder
+            batch_request: $variables.jan_2018_thru_nov_2020_monthly_trip_data_batch_request
+            metric_name: table.row_count
+            confidence_level: $variables.confidence_level
+            round_decimals: 0
+            truncate_values:
+              lower_bound: 0
+        expectation_configuration_builders:
+         - expectation_type: expect_table_row_count_to_be_between
+           class_name: DefaultExpectationConfigurationBuilder
+           module_name: great_expectations.rule_based_profiler.expectation_configuration_builder
+           min_value: $parameter.row_count_range.value.min_value
+           max_value: $parameter.row_count_range.value.max_value
+           mostly: $variables.mostly
+           meta:
+             profiler_details: $parameter.row_count_range.details
+    """
+    yaml = YAML()
+    return yaml.load(yaml_config)
+
+
 def test_expectation_suite_equality(baseline_suite, identical_suite, equivalent_suite):
     """Equality should depend on all defined properties of a configuration object, but not on whether the *instances*
     are the same."""
@@ -309,6 +354,18 @@ def test_add_citation(baseline_suite):
     assert baseline_suite.meta["citations"][0].get("comment") == "hello!"
 
 
+def test_add_citation_with_profiler_config(baseline_suite, profiler_config):
+    assert (
+        "citations" not in baseline_suite.meta
+        or len(baseline_suite.meta["citations"]) == 0
+    )
+    baseline_suite.add_citation(
+        "adding profiler config citation",
+        profiler_config=profiler_config,
+    )
+    assert baseline_suite.meta["citations"][0].get("profiler_config") == profiler_config
+
+
 def test_get_citations_with_no_citations(baseline_suite):
     assert "citations" not in baseline_suite.meta
     assert baseline_suite.get_citations() == []
@@ -401,6 +458,46 @@ def test_get_citations_with_multiple_citations_containing_batch_kwargs(baseline_
     ]
 
 
+def test_get_citations_with_multiple_citations_containing_profiler_config(
+    baseline_suite, profiler_config
+):
+    assert "citations" not in baseline_suite.meta
+
+    baseline_suite.add_citation(
+        "first",
+        citation_date="2000-01-01",
+        profiler_config=profiler_config,
+    )
+    baseline_suite.add_citation(
+        "second",
+        citation_date="2001-01-01",
+        profiler_config=profiler_config,
+    )
+    baseline_suite.add_citation("third", citation_date="2002-01-01")
+
+    properties_dict_list: List[Dict[str, Any]] = baseline_suite.get_citations(
+        sort=True, require_profiler_config=True
+    )
+    for properties_dict in properties_dict_list:
+        filter_properties_dict(
+            properties=properties_dict, clean_falsy=True, inplace=True
+        )
+        properties_dict.pop("interactive", None)
+
+    assert properties_dict_list == [
+        {
+            "citation_date": "2000-01-01T00:00:00.000000Z",
+            "profiler_config": profiler_config,
+            "comment": "first",
+        },
+        {
+            "citation_date": "2001-01-01T00:00:00.000000Z",
+            "profiler_config": profiler_config,
+            "comment": "second",
+        },
+    ]
+
+
 def test_get_table_expectations_returns_empty_list_on_empty_suite(empty_suite):
     assert empty_suite.get_table_expectations() == []