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/expectations/metrics/column_aggregate_metric_provider.py b/great_expectations/expectations/metrics/column_aggregate_metric_provider.py
--- a/great_expectations/expectations/metrics/column_aggregate_metric_provider.py
+++ b/great_expectations/expectations/metrics/column_aggregate_metric_provider.py
@@ -87,7 +87,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 if filter_column_isnull:
@@ -170,7 +169,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 sqlalchemy_engine: sa.engine.Engine = execution_engine.engine
@@ -234,7 +232,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 column = data[column_name]
diff --git a/great_expectations/expectations/metrics/map_metric_provider.py b/great_expectations/expectations/metrics/map_metric_provider.py
--- a/great_expectations/expectations/metrics/map_metric_provider.py
+++ b/great_expectations/expectations/metrics/map_metric_provider.py
@@ -133,7 +133,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 filter_column_isnull = kwargs.get(
@@ -205,7 +204,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 dialect = execution_engine.dialect_module
@@ -277,7 +275,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 column = data[column_name]
@@ -363,7 +360,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 filter_column_isnull = kwargs.get(
@@ -431,7 +427,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 sqlalchemy_engine: Engine = execution_engine.engine
@@ -516,7 +511,6 @@ def inner_func(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 column = data[column_name]
@@ -627,7 +621,6 @@ def inner_func(
                 column_A_name, column_B_name = get_dbms_compatible_column_names(
                     column_names=column_names,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 values = metric_fn(
@@ -691,7 +684,6 @@ def inner_func(
                 column_A_name, column_B_name = get_dbms_compatible_column_names(
                     column_names=column_names,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 column_pair_function = metric_fn(
@@ -759,7 +751,6 @@ def inner_func(
                 column_A_name, column_B_name = get_dbms_compatible_column_names(
                     column_names=column_names,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 column_pair_function = metric_fn(
@@ -855,7 +846,6 @@ def inner_func(
                 column_A_name, column_B_name = get_dbms_compatible_column_names(
                     column_names=column_names,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 meets_expectation_series = metric_fn(
@@ -927,7 +917,6 @@ def inner_func(
                 column_A_name, column_B_name = get_dbms_compatible_column_names(
                     column_names=column_names,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 sqlalchemy_engine: Engine = execution_engine.engine
@@ -1007,7 +996,6 @@ def inner_func(
                 column_A_name, column_B_name = get_dbms_compatible_column_names(
                     column_names=column_names,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 expected_condition = metric_fn(
@@ -1092,7 +1080,6 @@ def inner_func(
                 column_list = get_dbms_compatible_column_names(
                     column_names=column_list,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 values = metric_fn(
@@ -1151,7 +1138,6 @@ def inner_func(
                 column_list = get_dbms_compatible_column_names(
                     column_names=column_list,
                     batch_columns_list=table_columns,
-                    execution_engine=execution_engine,
                 )
 
                 sqlalchemy_engine: Engine = execution_engine.engine
@@ -1223,7 +1209,6 @@ def inner_func(
                 column_list = get_dbms_compatible_column_names(
                     column_names=column_list,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 multicolumn_function = metric_fn(
@@ -1312,7 +1297,6 @@ def inner_func(
                 column_list = get_dbms_compatible_column_names(
                     column_names=column_list,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 meets_expectation_series = metric_fn(
@@ -1377,7 +1361,6 @@ def inner_func(
                 column_list = get_dbms_compatible_column_names(
                     column_names=column_list,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 sqlalchemy_engine: Engine = execution_engine.engine
@@ -1453,7 +1436,6 @@ def inner_func(
                 column_list = get_dbms_compatible_column_names(
                     column_names=column_list,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                 )
 
                 expected_condition = metric_fn(
@@ -1518,7 +1500,6 @@ def _pandas_column_map_condition_values(
     column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     ###
@@ -1587,7 +1568,6 @@ def _pandas_column_pair_map_condition_values(
     column_A_name, column_B_name = get_dbms_compatible_column_names(
         column_names=column_names,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     domain_values = df[column_names]
@@ -1680,7 +1660,6 @@ def _pandas_multicolumn_map_condition_values(
     column_list = get_dbms_compatible_column_names(
         column_names=column_list,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     domain_values = df[column_list]
@@ -1769,7 +1748,6 @@ def _pandas_column_map_series_and_domain_values(
     column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     ###
@@ -1832,7 +1810,6 @@ def _pandas_map_condition_index(
         column_name = get_dbms_compatible_column_names(
             column_names=column_name,
             batch_columns_list=metrics["table.columns"],
-            execution_engine=execution_engine,
         )
 
         ###
@@ -1914,7 +1891,6 @@ def _pandas_map_condition_query(
         column_name = get_dbms_compatible_column_names(
             column_names=column_name,
             batch_columns_list=metrics["table.columns"],
-            execution_engine=execution_engine,
         )
         filter_column_isnull = kwargs.get(
             "filter_column_isnull", getattr(cls, "filter_column_isnull", False)
@@ -1963,7 +1939,6 @@ def _pandas_column_map_condition_value_counts(
     column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     ###
@@ -2029,7 +2004,6 @@ def _pandas_map_condition_rows(
         column_name = get_dbms_compatible_column_names(
             column_names=column_name,
             batch_columns_list=metrics["table.columns"],
-            execution_engine=execution_engine,
         )
 
         ###
@@ -2215,7 +2189,6 @@ def _sqlalchemy_column_map_condition_values(
     column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     query = sa.select([sa.column(column_name).label("unexpected_values")]).where(
@@ -2277,7 +2250,6 @@ def _sqlalchemy_column_pair_map_condition_values(
     column_A_name, column_B_name = get_dbms_compatible_column_names(
         column_names=column_names,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     query = sa.select(
@@ -2366,7 +2338,6 @@ def _sqlalchemy_multicolumn_map_condition_values(
     column_list = get_dbms_compatible_column_names(
         column_names=column_list,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     column_selector = [sa.column(column_name) for column_name in column_list]
@@ -2449,7 +2420,6 @@ def _sqlalchemy_column_map_condition_value_counts(
     column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     column: sa.Column = sa.column(column_name)
@@ -2723,7 +2693,6 @@ def _spark_column_map_condition_values(
     column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     # withColumn is required to transform window functions returned by some metrics to boolean mask
@@ -2770,7 +2739,6 @@ def _spark_column_map_condition_value_counts(
     column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     df: pyspark.sql.dataframe.DataFrame = execution_engine.get_domain_records(
@@ -2977,7 +2945,6 @@ def _spark_column_pair_map_condition_values(
     column_A_name, column_B_name = get_dbms_compatible_column_names(
         column_names=column_names,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     # withColumn is required to transform window functions returned by some metrics to boolean mask
@@ -3073,7 +3040,6 @@ def _spark_multicolumn_map_condition_values(
     column_list = get_dbms_compatible_column_names(
         column_names=column_list,
         batch_columns_list=metrics["table.columns"],
-        execution_engine=execution_engine,
     )
 
     # withColumn is required to transform window functions returned by some metrics to boolean mask
diff --git a/great_expectations/expectations/metrics/util.py b/great_expectations/expectations/metrics/util.py
--- a/great_expectations/expectations/metrics/util.py
+++ b/great_expectations/expectations/metrics/util.py
@@ -3,7 +3,7 @@
 import logging
 import re
 import warnings
-from typing import TYPE_CHECKING, Any, Dict, List, Optional, overload
+from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, overload
 
 import numpy as np
 import pandas as pd
@@ -12,7 +12,6 @@
 
 import great_expectations.exceptions as gx_exceptions
 from great_expectations.execution_engine import (
-    ExecutionEngine,
     PandasExecutionEngine,
     SqlAlchemyExecutionEngine,
 )
@@ -632,7 +631,6 @@ def column_reflection_fallback(
 def get_dbms_compatible_column_names(
     column_names: str,
     batch_columns_list: List[str | sqlalchemy.sql.quoted_name],
-    execution_engine: ExecutionEngine,
     error_message_template: str = ...,
 ) -> str | sqlalchemy.sql.quoted_name:
     ...
@@ -642,7 +640,6 @@ def get_dbms_compatible_column_names(
 def get_dbms_compatible_column_names(
     column_names: List[str],
     batch_columns_list: List[str | sqlalchemy.sql.quoted_name],
-    execution_engine: ExecutionEngine,
     error_message_template: str = ...,
 ) -> List[str | sqlalchemy.sql.quoted_name]:
     ...
@@ -651,7 +648,6 @@ def get_dbms_compatible_column_names(
 def get_dbms_compatible_column_names(
     column_names: List[str] | str,
     batch_columns_list: List[str | sqlalchemy.sql.quoted_name],
-    execution_engine: ExecutionEngine,
     error_message_template: str = 'Error: The column "{column_name:s}" in BatchData does not exist.',
 ) -> List[str | sqlalchemy.sql.quoted_name] | str | sqlalchemy.sql.quoted_name:
     """
@@ -666,43 +662,30 @@ def get_dbms_compatible_column_names(
     Args:
         column_names: Single string-valued column name or list of string-valued column names
         batch_columns_list: Properly typed column names (output of "table.columns" metric)
-        execution_engine: "ExecutionEngine" (here, of interest is whether or not "SqlAlchemyExecutionEngine" is used)
         error_message_template: String template to output error message if any column cannot be found in "Batch" object.
 
     Returns:
         Single property-typed column name object or list of property-typed column name objects (depending on input).
     """
-    verify_column_names_exist(
-        column_names=column_names,
-        batch_columns_list=batch_columns_list,
-        error_message_template=error_message_template,
+    normalized_typed_batch_columns_mappings: List[
+        Tuple[str, str | sqlalchemy.sql.quoted_name]
+    ] = (
+        _verify_column_names_exist_and_get_normalized_typed_column_names_map(
+            column_names=column_names,
+            batch_columns_list=batch_columns_list,
+            error_message_template=error_message_template,
+        )
+        or []
     )
 
-    column_names_list: List[str]
-    is_list: bool
+    element: Tuple[str, str | sqlalchemy.sql.quoted_name]
+    typed_batch_column_names_list: List[str | sqlalchemy.sql.quoted_name] = [
+        element[1] for element in normalized_typed_batch_columns_mappings
+    ]
     if isinstance(column_names, list):
-        column_names_list = column_names
-        is_list = True
-    else:
-        column_names_list = [column_names]
-        is_list = False
-
-    typed_column_names_list: List[str | sqlalchemy.sql.quoted_name]
-    if isinstance(execution_engine, SqlAlchemyExecutionEngine):
-        column_name: str
-        batch_columns_dict: Dict[str, str | sqlalchemy.sql.quoted_name] = {
-            str(column_name): column_name for column_name in batch_columns_list
-        }
-        typed_column_names_list = [
-            batch_columns_dict[column_name] for column_name in column_names_list
-        ]
-    else:
-        typed_column_names_list = column_names_list
+        return typed_batch_column_names_list
 
-    if is_list:
-        return typed_column_names_list
-
-    return typed_column_names_list[0]
+    return typed_batch_column_names_list[0]
 
 
 def verify_column_names_exist(
@@ -710,13 +693,31 @@ def verify_column_names_exist(
     batch_columns_list: List[str | sqlalchemy.sql.quoted_name],
     error_message_template: str = 'Error: The column "{column_name:s}" in BatchData does not exist.',
 ) -> None:
+    _ = _verify_column_names_exist_and_get_normalized_typed_column_names_map(
+        column_names=column_names,
+        batch_columns_list=batch_columns_list,
+        error_message_template=error_message_template,
+        verify_only=True,
+    )
+
+
+def _verify_column_names_exist_and_get_normalized_typed_column_names_map(
+    column_names: List[str] | str,
+    batch_columns_list: List[str | sqlalchemy.sql.quoted_name],
+    error_message_template: str = 'Error: The column "{column_name:s}" in BatchData does not exist.',
+    verify_only: bool = False,
+) -> List[Tuple[str, str | sqlalchemy.sql.quoted_name]] | None:
     """
     Insures that column name or column names (supplied as argument using "str" representation) exist in "Batch" object.
 
     Args:
         column_names: Single string-valued column name or list of string-valued column names
         batch_columns_list: Properly typed column names (output of "table.columns" metric)
+        verify_only: Perform verification only (do not return normalized typed column names)
         error_message_template: String template to output error message if any column cannot be found in "Batch" object.
+
+    Returns:
+        List of tuples having mapping from string-valued column name to typed column name; None if "verify_only" is set.
     """
     column_names_list: List[str]
     if isinstance(column_names, list):
@@ -724,15 +725,38 @@ def verify_column_names_exist(
     else:
         column_names_list = [column_names]
 
-    column_name: str
+    def _get_normalized_column_name_mapping_if_exists(
+        column_name: str,
+    ) -> Tuple[str, str | sqlalchemy.sql.quoted_name] | None:
+        typed_column_name_cursor: str | sqlalchemy.sql.quoted_name
+        for typed_column_name_cursor in batch_columns_list:
+            if (
+                (type(typed_column_name_cursor) == str)
+                and (column_name.casefold() == typed_column_name_cursor.casefold())
+            ) or (column_name == str(typed_column_name_cursor)):
+                return column_name, typed_column_name_cursor
+
+        return None
 
-    batch_columns_list = [str(column_name) for column_name in batch_columns_list]
+    normalized_batch_columns_mappings: List[
+        Tuple[str, str | sqlalchemy.sql.quoted_name]
+    ] = []
 
+    normalized_column_name_mapping: Tuple[str, str | sqlalchemy.sql.quoted_name] | None
+    column_name: str
     for column_name in column_names_list:
-        if column_name not in batch_columns_list:
+        normalized_column_name_mapping = _get_normalized_column_name_mapping_if_exists(
+            column_name=column_name
+        )
+        if normalized_column_name_mapping is None:
             raise gx_exceptions.InvalidMetricAccessorDomainKwargsKeyError(
                 message=error_message_template.format(column_name=column_name)
             )
+        else:
+            if not verify_only:
+                normalized_batch_columns_mappings.append(normalized_column_name_mapping)
+
+    return None if verify_only else normalized_batch_columns_mappings
 
 
 def parse_value_set(value_set):
@@ -1256,7 +1280,6 @@ def compute_unexpected_pandas_indices(
                 column_name = get_dbms_compatible_column_names(
                     column_names=column_name,
                     batch_columns_list=metrics["table.columns"],
-                    execution_engine=execution_engine,
                     error_message_template='Error: The unexpected_index_column "{column_name:s}" does not exist in Dataframe. Please check your configuration and try again.',
                 )
                 primary_key_dict[column_name] = domain_records_df.at[index, column_name]


Test patch:
diff --git a/tests/expectations/metrics/test_core.py b/tests/expectations/metrics/test_core.py
--- a/tests/expectations/metrics/test_core.py
+++ b/tests/expectations/metrics/test_core.py
@@ -201,9 +201,11 @@ def test_column_quoted_name_type_sa(sa):
     )
     table_columns_metric_id: Tuple[str, str, str] = table_columns_metric.id
     batch_column_list = metrics[table_columns_metric_id]
+
+    column_name: str
     quoted_batch_column_list = [
-        quoted_name(value=str(element), quote=True)
-        for element in metrics[table_columns_metric_id]
+        quoted_name(value=str(column_name), quote=True)
+        for column_name in batch_column_list
     ]
 
     column_name = "names"
@@ -211,21 +213,18 @@ def test_column_quoted_name_type_sa(sa):
     str_column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=batch_column_list,
-        execution_engine=PandasExecutionEngine(),
     )
     assert isinstance(str_column_name, str)
 
     quoted_column_name = get_dbms_compatible_column_names(
         column_names=column_name,
         batch_columns_list=quoted_batch_column_list,
-        execution_engine=engine,
     )
     assert isinstance(quoted_column_name, sa.sql.elements.quoted_name)
     assert quoted_column_name.quote is True
 
     for column_name in [
         "non_existent_column",
-        "NAMES",
         '"NAMES"',
         '"Names"',
     ]:
@@ -235,19 +234,29 @@ def test_column_quoted_name_type_sa(sa):
             _ = get_dbms_compatible_column_names(
                 column_names=column_name,
                 batch_columns_list=batch_column_list,
-                execution_engine=engine,
             )
         assert (
             str(eee.value)
             == f'Error: The column "{column_name}" in BatchData does not exist.'
         )
+
+    quoted_batch_column_list = [
+        quoted_name(value=str(column_name), quote=True)
+        for column_name in [
+            "Names",
+            "names",
+        ]
+    ]
+    for column_name in [
+        "non_existent_column",
+        "NAMES",
+    ]:
         with pytest.raises(
             gx_exceptions.InvalidMetricAccessorDomainKwargsKeyError
         ) as eee:
             _ = get_dbms_compatible_column_names(
                 column_names=column_name,
                 batch_columns_list=quoted_batch_column_list,
-                execution_engine=engine,
             )
         assert (
             str(eee.value)