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/split_and_sample/sqlalchemy_data_splitter.py b/great_expectations/execution_engine/split_and_sample/sqlalchemy_data_splitter.py
--- a/great_expectations/execution_engine/split_and_sample/sqlalchemy_data_splitter.py
+++ b/great_expectations/execution_engine/split_and_sample/sqlalchemy_data_splitter.py
@@ -196,20 +196,24 @@ def split_on_column_value(column_name: str, batch_identifiers: dict) -> bool:
 
         return sa.column(column_name) == batch_identifiers[column_name]
 
-    @staticmethod
     def split_on_converted_datetime(
+        self,
         column_name: str,
         batch_identifiers: dict,
         date_format_string: str = "%Y-%m-%d",
     ) -> bool:
         """Convert the values in the named column to the given date_format, and split on that"""
-
-        return (
-            sa.func.strftime(
-                date_format_string,
-                sa.column(column_name),
+        if self._dialect == "sqlite":
+            return (
+                sa.func.strftime(
+                    date_format_string,
+                    sa.column(column_name),
+                )
+                == batch_identifiers[column_name]
             )
-            == batch_identifiers[column_name]
+
+        raise NotImplementedError(
+            f'Splitter method "split_on_converted_datetime" is not supported for "{self._dialect}" SQL dialect.'
         )
 
     def split_on_divided_integer(
@@ -715,23 +719,28 @@ def get_split_query_for_data_for_batch_identifiers_for_split_on_column_value(
             .order_by(sa.column(column_name).asc())
         )
 
-    @staticmethod
     def get_split_query_for_data_for_batch_identifiers_for_split_on_converted_datetime(
+        self,
         table_name: str,
         column_name: str,
         date_format_string: str = "%Y-%m-%d",
     ) -> Selectable:
         """Convert the values in the named column to the given date_format, and split on that"""
-        return sa.select(
-            [
-                sa.func.distinct(
-                    sa.func.strftime(
-                        date_format_string,
-                        sa.column(column_name),
+        if self._dialect == "sqlite":
+            return sa.select(
+                [
+                    sa.func.distinct(
+                        sa.func.strftime(
+                            date_format_string,
+                            sa.column(column_name),
+                        )
                     )
-                )
-            ]
-        ).select_from(sa.text(table_name))
+                ]
+            ).select_from(sa.text(table_name))
+
+        raise NotImplementedError(
+            f'Splitter method "split_on_converted_datetime" is not supported for "{self._dialect}" SQL dialect.'
+        )
 
     def get_split_query_for_data_for_batch_identifiers_for_split_on_divided_integer(
         self,


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -6625,11 +6625,16 @@ def quentin_columnar_table_multi_batch():
 @pytest.fixture
 def quentin_columnar_table_multi_batch_data_context(
     tmp_path_factory,
+    monkeypatch,
 ) -> DataContext:
     """
     This fixture generates three years' worth (36 months; i.e., 36 batches) of taxi trip data with the number of rows
     of each batch being equal to the original number per log file (10,000 rows).
     """
+    # Re-enable GE_USAGE_STATS
+    monkeypatch.delenv("GE_USAGE_STATS")
+    monkeypatch.setattr(AnonymizedUsageStatisticsConfig, "enabled", True)
+
     project_path: str = str(tmp_path_factory.mktemp("taxi_data_context"))
     context_path: str = os.path.join(project_path, "great_expectations")
     os.makedirs(os.path.join(context_path, "expectations"), exist_ok=True)
@@ -6675,19 +6680,6 @@ def quentin_columnar_table_multi_batch_data_context(
     return context
 
 
-@pytest.fixture
-def quentin_columnar_table_multi_batch_data_context_usage_stats_enabled(
-    quentin_columnar_table_multi_batch_data_context, monkeypatch
-) -> DataContext:
-    context: DataContext = quentin_columnar_table_multi_batch_data_context
-
-    # Re-enable GE_USAGE_STATS
-    monkeypatch.delenv("GE_USAGE_STATS")
-    monkeypatch.setattr(AnonymizedUsageStatisticsConfig, "enabled", True)
-
-    return context
-
-
 # TODO: AJB 20210525 This fixture is not yet used but may be helpful to generate batches for unit tests of multibatch
 #  workflows.  It should probably be extended to add different column types / data.
 @pytest.fixture
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
@@ -1,6 +1,6 @@
 import datetime
 import os
-from typing import List
+from typing import List, Optional
 from unittest import mock
 
 import pandas as pd
@@ -31,6 +31,7 @@
     TaxiSplittingTestCase,
     TaxiSplittingTestCasesBase,
     TaxiSplittingTestCasesColumnValue,
+    TaxiSplittingTestCasesConvertedDateTime,
     TaxiSplittingTestCasesDateTime,
     TaxiSplittingTestCasesDividedInteger,
     TaxiSplittingTestCasesHashedColumn,
@@ -39,6 +40,7 @@
     TaxiSplittingTestCasesWholeTable,
     TaxiTestData,
 )
+from tests.test_utils import convert_string_columns_to_datetime
 
 SINGLE_DATE_PART_DATE_PARTS += [
     pytest.param(
@@ -395,18 +397,17 @@ def ten_trips_per_month_df() -> pd.DataFrame:
             "yellow_tripdata_sample_10_trips_from_each_month.csv",
         ),
     )
-    # Convert pickup_datetime to a datetime type column
     df: pd.DataFrame = pd.read_csv(csv_path)
-    column_names_to_convert: List[str] = ["pickup_datetime", "dropoff_datetime"]
-    for column_name_to_convert in column_names_to_convert:
-        df[column_name_to_convert] = pd.to_datetime(df[column_name_to_convert])
-
     return df
 
 
 @pytest.fixture
 def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
-    engine: SqlAlchemyExecutionEngine = build_sa_engine(ten_trips_per_month_df(), sa)
+    df: pd.DataFrame = ten_trips_per_month_df()
+    convert_string_columns_to_datetime(
+        df=df, column_names_to_convert=["pickup_datetime", "dropoff_datetime"]
+    )
+    engine: SqlAlchemyExecutionEngine = build_sa_engine(df, sa)
     return engine
 
 
@@ -419,6 +420,7 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                 test_df=ten_trips_per_month_df(),
                 test_column_name=None,
                 test_column_names=None,
+                column_names_to_convert=["pickup_datetime", "dropoff_datetime"],
             )
         ),
         TaxiSplittingTestCasesColumnValue(
@@ -426,6 +428,7 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                 test_df=ten_trips_per_month_df(),
                 test_column_name="passenger_count",
                 test_column_names=None,
+                column_names_to_convert=["pickup_datetime", "dropoff_datetime"],
             )
         ),
         TaxiSplittingTestCasesDividedInteger(
@@ -433,6 +436,7 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                 test_df=ten_trips_per_month_df(),
                 test_column_name="pickup_location_id",
                 test_column_names=None,
+                column_names_to_convert=["pickup_datetime", "dropoff_datetime"],
             )
         ),
         TaxiSplittingTestCasesModInteger(
@@ -440,6 +444,7 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                 test_df=ten_trips_per_month_df(),
                 test_column_name="pickup_location_id",
                 test_column_names=None,
+                column_names_to_convert=["pickup_datetime", "dropoff_datetime"],
             )
         ),
         TaxiSplittingTestCasesHashedColumn(
@@ -447,6 +452,7 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                 test_df=ten_trips_per_month_df(),
                 test_column_name="pickup_location_id",
                 test_column_names=None,
+                column_names_to_convert=["pickup_datetime", "dropoff_datetime"],
             )
         ),
         TaxiSplittingTestCasesMultiColumnValues(
@@ -457,6 +463,7 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                     "rate_code_id",
                     "payment_type",
                 ],
+                column_names_to_convert=["pickup_datetime", "dropoff_datetime"],
             )
         ),
         TaxiSplittingTestCasesDateTime(
@@ -464,6 +471,15 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
                 test_df=ten_trips_per_month_df(),
                 test_column_name="pickup_datetime",
                 test_column_names=None,
+                column_names_to_convert=["pickup_datetime", "dropoff_datetime"],
+            )
+        ),
+        TaxiSplittingTestCasesConvertedDateTime(
+            taxi_test_data=TaxiTestData(
+                test_df=ten_trips_per_month_df(),
+                test_column_name="pickup_datetime",
+                test_column_names=None,
+                column_names_to_convert=None,
             )
         ),
     ],
@@ -471,15 +487,11 @@ def in_memory_sqlite_taxi_ten_trips_per_month_execution_engine(sa):
 def test_sqlite_split(
     taxi_test_cases: TaxiSplittingTestCasesBase,
     sa,
-    in_memory_sqlite_taxi_ten_trips_per_month_execution_engine,
 ):
     """What does this test and why?
     splitters should work with sqlite.
     """
-
-    engine: SqlAlchemyExecutionEngine = (
-        in_memory_sqlite_taxi_ten_trips_per_month_execution_engine
-    )
+    engine: SqlAlchemyExecutionEngine = build_sa_engine(taxi_test_cases.test_df, sa)
 
     test_cases: List[TaxiSplittingTestCase] = taxi_test_cases.test_cases()
     test_case: TaxiSplittingTestCase
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
@@ -7,6 +7,7 @@
 import pandas as pd
 
 from great_expectations.execution_engine.split_and_sample.data_splitter import DatePart
+from tests.test_utils import convert_string_columns_to_datetime
 
 
 class TaxiTestData:
@@ -15,9 +16,8 @@ def __init__(
         test_df: pd.DataFrame,
         test_column_name: Optional[str] = None,
         test_column_names: Optional[List[str]] = None,
+        column_names_to_convert: Optional[List[str]] = None,
     ):
-        self._test_df = test_df
-
         if (
             sum(
                 bool(x)
@@ -35,6 +35,13 @@ def __init__(
         self._test_column_name = test_column_name
         self._test_column_names = test_column_names
 
+        # Convert specified columns (e.g., "pickup_datetime" and "dropoff_datetime") to datetime column type.
+        convert_string_columns_to_datetime(
+            df=test_df, column_names_to_convert=column_names_to_convert
+        )
+
+        self._test_df = test_df
+
     @property
     def test_df(self) -> pd.DataFrame:
         return self._test_df
@@ -66,6 +73,12 @@ def months_in_taxi_data() -> List[datetime.datetime]:
             .tolist()
         )
 
+    def get_unique_sorted_months_in_taxi_data(self) -> List[str]:
+        months: List[datetime.datetime] = sorted(set(self.months_in_taxi_data()))
+
+        month: datetime.datetime
+        return [month.strftime("%Y-%m-%d") for month in months]
+
     def year_month_batch_identifier_data(self) -> List[dict]:
         return [
             {DatePart.YEAR.value: dt.year, DatePart.MONTH.value: dt.month}
@@ -417,3 +430,20 @@ def test_cases(self) -> List[TaxiSplittingTestCase]:
                 expected_column_values=self.taxi_test_data.year_month_batch_identifier_data(),
             ),
         ]
+
+
+class TaxiSplittingTestCasesConvertedDateTime(TaxiSplittingTestCasesBase):
+    def test_cases(self) -> List[TaxiSplittingTestCase]:
+        return [
+            TaxiSplittingTestCase(
+                table_domain_test_case=False,
+                splitter_method_name="split_on_converted_datetime",
+                splitter_kwargs={
+                    "column_name": self.taxi_test_data.test_column_name,
+                    "date_format_string": "%Y-%m-%d",
+                },
+                num_expected_batch_definitions=9,
+                num_expected_rows_in_first_batch_definition=2,
+                expected_column_values=self.taxi_test_data.get_unique_sorted_months_in_taxi_data(),
+            ),
+        ]
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
@@ -1082,6 +1082,111 @@ class IntegrationTestFixture:
         ),
         extra_backend_dependencies=BackendDependencies.MSSQL,
     ),
+    # TODO: <Alex>ALEX -- Uncomment next statement when "split_on_converted_datetime" for POSTGRESQL is implemented.</Alex>
+    # IntegrationTestFixture(
+    #     name="split_data_on_converted_datetime_postgres",
+    #     user_flow_script="tests/integration/db/test_sql_data_split_on_converted_datetime.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,
+    # ),
+    # TODO: <Alex>ALEX -- Uncomment next statement when "split_on_converted_datetime" for REDSHIFT is implemented.</Alex>
+    # IntegrationTestFixture(
+    #     name="split_data_on_converted_datetime_redshift",
+    #     user_flow_script="tests/integration/db/test_sql_data_split_on_converted_datetime.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,
+    # ),
+    # TODO: <Alex>ALEX -- Uncomment next statement when "split_on_converted_datetime" for MSSQL is implemented.</Alex>
+    # IntegrationTestFixture(
+    #     name="split_data_on_converted_datetime_mssql",
+    #     user_flow_script="tests/integration/db/test_sql_data_split_on_converted_datetime.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,
+    # ),
+    # TODO: <Alex>ALEX -- Uncomment next statement when "split_on_converted_datetime" for MYSQL is implemented.</Alex>
+    # IntegrationTestFixture(
+    #     name="split_data_on_converted_datetime_mysql",
+    #     user_flow_script="tests/integration/db/test_sql_data_split_on_converted_datetime.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,
+    # ),
+    # TODO: <Alex>ALEX -- Uncomment next statement when "split_on_converted_datetime" for SNOWFLAKE is implemented.</Alex>
+    # IntegrationTestFixture(
+    #     name="split_data_on_converted_datetime_snowflake",
+    #     user_flow_script="tests/integration/db/test_sql_data_split_on_converted_datetime.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,
+    # ),
+    # TODO: <Alex>ALEX -- Uncomment next statement when "split_on_converted_datetime" for BIGQUERY is implemented.</Alex>
+    # IntegrationTestFixture(
+    #     name="split_data_on_converted_datetime_bigquery",
+    #     user_flow_script="tests/integration/db/test_sql_data_split_on_converted_datetime.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,
+    # ),
+    # TODO: <Alex>ALEX -- Uncomment next statement when "split_on_converted_datetime" for AWS ATHENA is implemented.</Alex>
+    # IntegrationTestFixture(
+    #     name="split_data_on_converted_datetime_awsathena",
+    #     user_flow_script="tests/integration/db/test_sql_data_split_on_converted_datetime.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="sample_data_using_limit_mysql",
         user_flow_script="tests/integration/db/test_sql_data_sampling.py",
diff --git a/tests/render/test_inline_renderer.py b/tests/render/test_inline_renderer.py
--- a/tests/render/test_inline_renderer.py
+++ b/tests/render/test_inline_renderer.py
@@ -32,14 +32,6 @@
                         "schema": {"type": "com.superconductive.rendered.string"},
                         "params": {
                             "value": {"schema": {"type": "number"}, "value": 3},
-                            "row_condition": {
-                                "schema": {"type": "string"},
-                                "value": None,
-                            },
-                            "condition_parser": {
-                                "schema": {"type": "string"},
-                                "value": None,
-                            },
                         },
                     },
                 }
diff --git a/tests/test_utils.py b/tests/test_utils.py
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -553,8 +553,9 @@ def load_and_concatenate_csvs(
     dfs: List[pd.DataFrame] = []
     for csv_path in csv_paths:
         df = pd.read_csv(csv_path)
-        for column_name_to_convert in convert_column_names_to_datetime:
-            df[column_name_to_convert] = pd.to_datetime(df[column_name_to_convert])
+        convert_string_columns_to_datetime(
+            df=df, column_names_to_convert=convert_column_names_to_datetime
+        )
         if not load_full_dataset:
             # Improving test performance by only loading the first 10 rows of our test data into the db
             df = df.head(10)
@@ -566,6 +567,21 @@ def load_and_concatenate_csvs(
     return all_dfs_concatenated
 
 
+def convert_string_columns_to_datetime(
+    df: pd.DataFrame, column_names_to_convert: Optional[List[str]] = None
+) -> None:
+    """
+    Converts specified columns (e.g., "pickup_datetime" and "dropoff_datetime") to datetime column type.
+    Side-effect: Passed DataFrame is modified (in-place).
+    """
+    if column_names_to_convert is None:
+        column_names_to_convert = []
+
+    column_name_to_convert: str
+    for column_name_to_convert in column_names_to_convert:
+        df[column_name_to_convert] = pd.to_datetime(df[column_name_to_convert])
+
+
 def load_data_into_test_database(
     table_name: str,
     connection_string: str,