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/execution_engine/execution_engine.py b/great_expectations/execution_engine/execution_engine.py
--- a/great_expectations/execution_engine/execution_engine.py
+++ b/great_expectations/execution_engine/execution_engine.py
@@ -240,8 +240,8 @@ def active_batch_data(self):
         """The data from the currently-active batch."""
         if self.active_batch_data_id is None:
             return None
-        else:
-            return self.loaded_batch_data_dict.get(self.active_batch_data_id)
+
+        return self.loaded_batch_data_dict.get(self.active_batch_data_id)
 
     @property
     def loaded_batch_data_dict(self):
@@ -608,6 +608,7 @@ def _split_table_metric_domain_kwargs(
                 logger.warning(
                     f'Unexpected key(s) {unexpected_keys_str} found in domain_kwargs for domain type "{domain_type.value}".'
                 )
+
         return SplitDomainKwargs(compute_domain_kwargs, accessor_domain_kwargs)
 
     @staticmethod
diff --git a/great_expectations/execution_engine/sqlalchemy_execution_engine.py b/great_expectations/execution_engine/sqlalchemy_execution_engine.py
--- a/great_expectations/execution_engine/sqlalchemy_execution_engine.py
+++ b/great_expectations/execution_engine/sqlalchemy_execution_engine.py
@@ -1073,6 +1073,7 @@ def _build_selectable_from_batch_spec(
                         )
                     )
                 )
+
         return (
             sa.select("*")
             .select_from(
diff --git a/great_expectations/execution_engine/util.py b/great_expectations/execution_engine/util.py
--- a/great_expectations/execution_engine/util.py
+++ b/great_expectations/execution_engine/util.py
@@ -35,6 +35,7 @@ def is_valid_categorical_partition_object(partition_object):
         or ("values" not in partition_object)
     ):
         return False
+
     # Expect the same number of values as weights; weights should sum to one
     return len(partition_object["values"]) == len(
         partition_object["weights"]


Test patch:
diff --git a/tests/execution_engine/split_and_sample/test_sqlalchemy_execution_engine_splitting.py b/tests/execution_engine/split_and_sample/test_sqlalchemy_execution_engine_splitting.py
--- a/tests/execution_engine/split_and_sample/test_sqlalchemy_execution_engine_splitting.py
+++ b/tests/execution_engine/split_and_sample/test_sqlalchemy_execution_engine_splitting.py
@@ -32,6 +32,7 @@
     TaxiSplittingTestCasesBase,
     TaxiSplittingTestCasesColumnValue,
     TaxiSplittingTestCasesDateTime,
+    TaxiSplittingTestCasesDividedInteger,
     TaxiSplittingTestCasesWholeTable,
     TaxiTestData,
 )
@@ -421,6 +422,12 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                 test_column_name="passenger_count",
             )
         ),
+        TaxiSplittingTestCasesDividedInteger(
+            taxi_test_data=TaxiTestData(
+                test_df=ten_trips_per_month_df(),
+                test_column_name="passenger_count",
+            )
+        ),
         TaxiSplittingTestCasesDateTime(
             taxi_test_data=TaxiTestData(
                 test_df=ten_trips_per_month_df(),
diff --git a/tests/integration/db/test_sql_data_split_on_divided_integer.py b/tests/integration/db/test_sql_data_split_on_divided_integer.py
new file mode 100644
--- /dev/null
+++ b/tests/integration/db/test_sql_data_split_on_divided_integer.py
@@ -0,0 +1,49 @@
+import numpy as np
+import pandas as pd
+
+from tests.integration.db.taxi_data_utils import (
+    _execute_taxi_splitting_test_cases,
+    _get_loaded_table,
+)
+from tests.integration.fixtures.split_and_sample_data.splitter_test_cases_and_fixtures import (
+    TaxiSplittingTestCasesBase,
+    TaxiSplittingTestCasesDividedInteger,
+    TaxiTestData,
+)
+from tests.test_utils import LoadedTable, get_connection_string_and_dialect
+
+if __name__ == "test_script_module":
+
+    dialect: str
+    connection_string: str
+    dialect, connection_string = get_connection_string_and_dialect(
+        athena_db_name_env_var="ATHENA_TEN_TRIPS_DB_NAME"
+    )
+    print(f"Testing dialect: {dialect}")
+
+    loaded_table: LoadedTable = _get_loaded_table(dialect=dialect)
+
+    table_name: str = loaded_table.table_name
+    test_df: pd.DataFrame = loaded_table.inserted_dataframe
+
+    test_column_name: str = "passenger_count"
+    df_null: pd.DataFrame = test_df[test_df[test_column_name].isnull()]
+    df_null[test_column_name] = df_null[test_column_name].apply(
+        lambda x: None if np.isnan(x) else x
+    )
+    df_nonnull: pd.DataFrame = test_df[~test_df[test_column_name].isnull()]
+    df_nonnull[test_column_name] = df_nonnull[test_column_name].astype(int)
+    test_df = pd.concat([df_null, df_nonnull])
+
+    taxi_test_data: TaxiTestData = TaxiTestData(
+        test_df=test_df,
+        test_column_name=test_column_name,
+    )
+    taxi_splitting_test_cases: TaxiSplittingTestCasesBase = (
+        TaxiSplittingTestCasesDividedInteger(taxi_test_data=taxi_test_data)
+    )
+    _execute_taxi_splitting_test_cases(
+        taxi_splitting_test_cases=taxi_splitting_test_cases,
+        connection_string=connection_string,
+        table_name=table_name,
+    )
diff --git a/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py b/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py
--- a/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py
+++ b/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py
@@ -76,12 +76,26 @@ def year_month_day_batch_identifier_data(self) -> List[dict]:
             ),
         )
 
-    def get_unique_test_column_values(self) -> List[Optional[Any]]:
-        return sorted(
+    def get_unique_test_column_values(
+        self,
+        reverse: Optional[bool] = False,
+        move_null_to_front: Optional[bool] = False,
+        limit: Optional[int] = None,
+    ) -> List[Optional[Any]]:
+        column_values: List[Optional[Any]] = sorted(
             self.test_df[self.test_column_name].unique().tolist(),
             key=lambda element: (element is None, element),
+            reverse=reverse,
         )
 
+        if move_null_to_front:
+            column_values = [None] + column_values[0:-1]
+
+        if limit is None:
+            return column_values
+
+        return column_values[:limit]
+
 
 @dataclass
 class TaxiSplittingTestCase:
@@ -144,6 +158,25 @@ def test_cases(self) -> List[TaxiSplittingTestCase]:
         ]
 
 
+class TaxiSplittingTestCasesDividedInteger(TaxiSplittingTestCasesBase):
+    def test_cases(self) -> List[TaxiSplittingTestCase]:
+        return [
+            TaxiSplittingTestCase(
+                table_domain_test_case=False,
+                splitter_method_name="split_on_divided_integer",
+                splitter_kwargs={
+                    "column_name": self.taxi_test_data.test_column_name,
+                    "divisor": 3,
+                },
+                num_expected_batch_definitions=4,
+                num_expected_rows_in_first_batch_definition=14,
+                expected_column_values=self.taxi_test_data.get_unique_test_column_values(
+                    move_null_to_front=True, limit=4
+                ),
+            ),
+        ]
+
+
 class TaxiSplittingTestCasesDateTime(TaxiSplittingTestCasesBase):
     def test_cases(self) -> List[TaxiSplittingTestCase]:
         return [
diff --git a/tests/integration/test_script_runner.py b/tests/integration/test_script_runner.py
--- a/tests/integration/test_script_runner.py
+++ b/tests/integration/test_script_runner.py
@@ -557,6 +557,104 @@ class IntegrationTestFixture:
         ),
         extra_backend_dependencies=BackendDependencies.AWS,
     ),
+    IntegrationTestFixture(
+        name="split_data_on_divided_integer_postgres",
+        user_flow_script="tests/integration/db/test_sql_data_split_on_divided_integer.py",
+        data_context_dir="tests/integration/fixtures/no_datasources/great_expectations",
+        data_dir="tests/test_sets/taxi_yellow_tripdata_samples/",
+        util_script="tests/test_utils.py",
+        other_files=(
+            (
+                "tests/integration/fixtures/split_and_sample_data/postgres_connection_string.yml",
+                "connection_string.yml",
+            ),
+        ),
+        extra_backend_dependencies=BackendDependencies.POSTGRESQL,
+    ),
+    IntegrationTestFixture(
+        name="split_data_on_divided_integer_redshift",
+        user_flow_script="tests/integration/db/test_sql_data_split_on_divided_integer.py",
+        data_context_dir="tests/integration/fixtures/no_datasources/great_expectations",
+        data_dir="tests/test_sets/taxi_yellow_tripdata_samples/",
+        util_script="tests/test_utils.py",
+        other_files=(
+            (
+                "tests/integration/fixtures/split_and_sample_data/redshift_connection_string.yml",
+                "connection_string.yml",
+            ),
+        ),
+        extra_backend_dependencies=BackendDependencies.REDSHIFT,
+    ),
+    IntegrationTestFixture(
+        name="split_data_on_divided_integer_mssql",
+        user_flow_script="tests/integration/db/test_sql_data_split_on_divided_integer.py",
+        data_context_dir="tests/integration/fixtures/no_datasources/great_expectations",
+        data_dir="tests/test_sets/taxi_yellow_tripdata_samples/",
+        util_script="tests/test_utils.py",
+        other_files=(
+            (
+                "tests/integration/fixtures/split_and_sample_data/mssql_connection_string.yml",
+                "connection_string.yml",
+            ),
+        ),
+        extra_backend_dependencies=BackendDependencies.MSSQL,
+    ),
+    IntegrationTestFixture(
+        name="split_data_on_divided_integer_mysql",
+        user_flow_script="tests/integration/db/test_sql_data_split_on_divided_integer.py",
+        data_context_dir="tests/integration/fixtures/no_datasources/great_expectations",
+        data_dir="tests/test_sets/taxi_yellow_tripdata_samples/",
+        util_script="tests/test_utils.py",
+        other_files=(
+            (
+                "tests/integration/fixtures/split_and_sample_data/mysql_connection_string.yml",
+                "connection_string.yml",
+            ),
+        ),
+        extra_backend_dependencies=BackendDependencies.MYSQL,
+    ),
+    IntegrationTestFixture(
+        name="split_data_on_divided_integer_snowflake",
+        user_flow_script="tests/integration/db/test_sql_data_split_on_divided_integer.py",
+        data_context_dir="tests/integration/fixtures/no_datasources/great_expectations",
+        data_dir="tests/test_sets/taxi_yellow_tripdata_samples/",
+        util_script="tests/test_utils.py",
+        other_files=(
+            (
+                "tests/integration/fixtures/split_and_sample_data/snowflake_connection_string.yml",
+                "connection_string.yml",
+            ),
+        ),
+        extra_backend_dependencies=BackendDependencies.SNOWFLAKE,
+    ),
+    IntegrationTestFixture(
+        name="split_data_on_divided_integer_bigquery",
+        user_flow_script="tests/integration/db/test_sql_data_split_on_divided_integer.py",
+        data_context_dir="tests/integration/fixtures/no_datasources/great_expectations",
+        data_dir="tests/test_sets/taxi_yellow_tripdata_samples/",
+        util_script="tests/test_utils.py",
+        other_files=(
+            (
+                "tests/integration/fixtures/split_and_sample_data/bigquery_connection_string.yml",
+                "connection_string.yml",
+            ),
+        ),
+        extra_backend_dependencies=BackendDependencies.BIGQUERY,
+    ),
+    IntegrationTestFixture(
+        name="split_data_on_divided_integer_awsathena",
+        user_flow_script="tests/integration/db/test_sql_data_split_on_divided_integer.py",
+        data_context_dir="tests/integration/fixtures/no_datasources/great_expectations",
+        data_dir="tests/test_sets/taxi_yellow_tripdata_samples/",
+        util_script="tests/test_utils.py",
+        other_files=(
+            (
+                "tests/integration/fixtures/split_and_sample_data/awsathena_connection_string.yml",
+                "connection_string.yml",
+            ),
+        ),
+        extra_backend_dependencies=BackendDependencies.AWS,
+    ),
     IntegrationTestFixture(
         name="split_data_on_datetime_postgres",
         user_flow_script="tests/integration/db/test_sql_data_split_on_datetime_and_day_part.py",