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/pandas_execution_engine.py b/great_expectations/execution_engine/pandas_execution_engine.py
--- a/great_expectations/execution_engine/pandas_execution_engine.py
+++ b/great_expectations/execution_engine/pandas_execution_engine.py
@@ -290,6 +290,12 @@ def get_domain_records(
         Returns:
             A DataFrame (the data on which to compute)
         """
+        table = domain_kwargs.get("table", None)
+        if table:
+            raise ValueError(
+                "PandasExecutionEngine does not currently support multiple named tables."
+            )
+
         batch_id = domain_kwargs.get("batch_id")
         if batch_id is None:
             # We allow no batch id specified if there is only one batch
@@ -327,56 +333,60 @@ def get_domain_records(
         if "column" in domain_kwargs:
             return data
 
-        if "column_A" in domain_kwargs and "column_B" in domain_kwargs:
-            if "ignore_row_if" in domain_kwargs:
-                # noinspection PyPep8Naming
-                column_A_name = domain_kwargs["column_A"]
-                # noinspection PyPep8Naming
-                column_B_name = domain_kwargs["column_B"]
-
-                ignore_row_if = domain_kwargs["ignore_row_if"]
-                if ignore_row_if == "both_values_are_missing":
-                    data = data.dropna(
-                        axis=0,
-                        how="all",
-                        subset=[column_A_name, column_B_name],
-                    )
-                elif ignore_row_if == "either_value_is_missing":
-                    data = data.dropna(
-                        axis=0,
-                        how="any",
-                        subset=[column_A_name, column_B_name],
-                    )
-                else:
-                    if ignore_row_if != "never":
-                        raise ValueError(
-                            f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
-                        )
-
-                return data
-
-        if "column_list" in domain_kwargs:
-            if "ignore_row_if" in domain_kwargs:
-                ignore_row_if = domain_kwargs["ignore_row_if"]
-                if ignore_row_if == "all_values_are_missing":
-                    data = data.dropna(
-                        axis=0,
-                        how="all",
-                        subset=domain_kwargs["column_list"],
+        if (
+            "column_A" in domain_kwargs
+            and "column_B" in domain_kwargs
+            and "ignore_row_if" in domain_kwargs
+        ):
+            # noinspection PyPep8Naming
+            column_A_name = domain_kwargs["column_A"]
+            # noinspection PyPep8Naming
+            column_B_name = domain_kwargs["column_B"]
+
+            ignore_row_if = domain_kwargs["ignore_row_if"]
+            if ignore_row_if == "both_values_are_missing":
+                data = data.dropna(
+                    axis=0,
+                    how="all",
+                    subset=[column_A_name, column_B_name],
+                )
+            elif ignore_row_if == "either_value_is_missing":
+                data = data.dropna(
+                    axis=0,
+                    how="any",
+                    subset=[column_A_name, column_B_name],
+                )
+            else:
+                if ignore_row_if != "never":
+                    raise ValueError(
+                        f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
                     )
-                elif ignore_row_if == "any_value_is_missing":
-                    data = data.dropna(
-                        axis=0,
-                        how="any",
-                        subset=domain_kwargs["column_list"],
+
+            return data
+
+        if "column_list" in domain_kwargs and "ignore_row_if" in domain_kwargs:
+            column_list = domain_kwargs["column_list"]
+
+            ignore_row_if = domain_kwargs["ignore_row_if"]
+            if ignore_row_if == "all_values_are_missing":
+                data = data.dropna(
+                    axis=0,
+                    how="all",
+                    subset=column_list,
+                )
+            elif ignore_row_if == "any_value_is_missing":
+                data = data.dropna(
+                    axis=0,
+                    how="any",
+                    subset=column_list,
+                )
+            else:
+                if ignore_row_if != "never":
+                    raise ValueError(
+                        f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
                     )
-                else:
-                    if ignore_row_if != "never":
-                        raise ValueError(
-                            f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
-                        )
 
-                return data
+            return data
 
         return data
 
@@ -456,17 +466,14 @@ class MetricDomainTypes.
                     )
             return data, compute_domain_kwargs, accessor_domain_kwargs
 
-        # If user has stated they want a column, checking if one is provided, and
         elif domain_type == MetricDomainTypes.COLUMN:
             if "column" in compute_domain_kwargs:
                 accessor_domain_kwargs["column"] = compute_domain_kwargs.pop("column")
             else:
-                # If column not given
                 raise ge_exceptions.GreatExpectationsError(
                     "Column not provided in compute_domain_kwargs"
                 )
 
-        # Else, if column pair values requested
         elif domain_type == MetricDomainTypes.COLUMN_PAIR:
             if not ("column_A" in domain_kwargs and "column_B" in domain_kwargs):
                 raise ge_exceptions.GreatExpectationsError(
@@ -476,7 +483,6 @@ class MetricDomainTypes.
             accessor_domain_kwargs["column_A"] = compute_domain_kwargs.pop("column_A")
             accessor_domain_kwargs["column_B"] = compute_domain_kwargs.pop("column_B")
 
-        # Checking if table or identity or other provided, column is not specified. If it is, warning the user
         elif domain_type == MetricDomainTypes.MULTICOLUMN:
             if "column_list" not in domain_kwargs:
                 raise ge_exceptions.GreatExpectationsError(
diff --git a/great_expectations/execution_engine/sparkdf_execution_engine.py b/great_expectations/execution_engine/sparkdf_execution_engine.py
--- a/great_expectations/execution_engine/sparkdf_execution_engine.py
+++ b/great_expectations/execution_engine/sparkdf_execution_engine.py
@@ -413,7 +413,6 @@ class MetricDomainTypes.
                     )
             return data, compute_domain_kwargs, accessor_domain_kwargs
 
-        # If user has stated they want a column, checking if one is provided, and
         elif domain_type == MetricDomainTypes.COLUMN:
             if "column" in compute_domain_kwargs:
                 accessor_domain_kwargs["column"] = compute_domain_kwargs.pop("column")
@@ -423,25 +422,18 @@ class MetricDomainTypes.
                     "Column not provided in compute_domain_kwargs"
                 )
 
-        # Else, if column pair values requested
         elif domain_type == MetricDomainTypes.COLUMN_PAIR:
-            # Ensuring column_A and column_B parameters provided
-            if (
+            if not (
                 "column_A" in compute_domain_kwargs
                 and "column_B" in compute_domain_kwargs
             ):
-                accessor_domain_kwargs["column_A"] = compute_domain_kwargs.pop(
-                    "column_A"
-                )
-                accessor_domain_kwargs["column_B"] = compute_domain_kwargs.pop(
-                    "column_B"
-                )
-            else:
                 raise GreatExpectationsError(
                     "column_A or column_B not found within compute_domain_kwargs"
                 )
 
-        # Checking if table or identity or other provided, column is not specified. If it is, warning the user
+            accessor_domain_kwargs["column_A"] = compute_domain_kwargs.pop("column_A")
+            accessor_domain_kwargs["column_B"] = compute_domain_kwargs.pop("column_B")
+
         elif domain_type == MetricDomainTypes.MULTICOLUMN:
             if "column_list" in compute_domain_kwargs:
                 # If column_list exists
@@ -449,14 +441,12 @@ class MetricDomainTypes.
                     "column_list"
                 )
 
-        # Filtering if identity
         elif domain_type == MetricDomainTypes.IDENTITY:
 
             # If we would like our data to become a single column
             if "column" in compute_domain_kwargs:
                 data = data.select(compute_domain_kwargs["column"])
 
-            # If we would like our data to now become a column pair
             elif ("column_A" in compute_domain_kwargs) and (
                 "column_B" in compute_domain_kwargs
             ):
@@ -465,7 +455,6 @@ class MetricDomainTypes.
                 )
             else:
 
-                # If we would like our data to become a multicolumn
                 if "column_list" in compute_domain_kwargs:
                     data = data.select(compute_domain_kwargs["column_list"])
 
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
@@ -386,7 +386,6 @@ def get_domain_records(
         Returns:
             An SqlAlchemy table/column(s) (the selectable object for obtaining data on which to compute)
         """
-        # Extracting value from enum if it is given for future computation
         batch_id = domain_kwargs.get("batch_id")
         if batch_id is None:
             # We allow no batch id specified if there is only one batch
@@ -444,104 +443,106 @@ def get_domain_records(
         if "column" in domain_kwargs:
             return selectable
 
-        if "column_A" in domain_kwargs and "column_B" in domain_kwargs:
-            if "ignore_row_if" in domain_kwargs:
-                if self.active_batch_data.use_quoted_name:
-                    # If case matters...
-                    # noinspection PyPep8Naming
-                    column_A_name = quoted_name(domain_kwargs["column_A"])
-                    # noinspection PyPep8Naming
-                    column_B_name = quoted_name(domain_kwargs["column_B"])
-                else:
-                    # noinspection PyPep8Naming
-                    column_A_name = domain_kwargs["column_A"]
-                    # noinspection PyPep8Naming
-                    column_B_name = domain_kwargs["column_B"]
-
-                ignore_row_if = domain_kwargs["ignore_row_if"]
-                if ignore_row_if == "both_values_are_missing":
-                    selectable = (
-                        sa.select([sa.text("*")])
-                        .select_from(selectable)
-                        .where(
-                            sa.not_(
-                                sa.and_(
-                                    sa.column(column_A_name) == None,
-                                    sa.column(column_B_name) == None,
-                                )
+        if (
+            "column_A" in domain_kwargs
+            and "column_B" in domain_kwargs
+            and "ignore_row_if" in domain_kwargs
+        ):
+            if self.active_batch_data.use_quoted_name:
+                # Checking if case-sensitive and using appropriate name
+                # noinspection PyPep8Naming
+                column_A_name = quoted_name(domain_kwargs["column_A"])
+                # noinspection PyPep8Naming
+                column_B_name = quoted_name(domain_kwargs["column_B"])
+            else:
+                # noinspection PyPep8Naming
+                column_A_name = domain_kwargs["column_A"]
+                # noinspection PyPep8Naming
+                column_B_name = domain_kwargs["column_B"]
+
+            ignore_row_if = domain_kwargs["ignore_row_if"]
+            if ignore_row_if == "both_values_are_missing":
+                selectable = (
+                    sa.select([sa.text("*")])
+                    .select_from(selectable)
+                    .where(
+                        sa.not_(
+                            sa.and_(
+                                sa.column(column_A_name) == None,
+                                sa.column(column_B_name) == None,
                             )
                         )
                     )
-                elif ignore_row_if == "either_value_is_missing":
-                    selectable = (
-                        sa.select([sa.text("*")])
-                        .select_from(selectable)
-                        .where(
-                            sa.not_(
-                                sa.or_(
-                                    sa.column(column_A_name) == None,
-                                    sa.column(column_B_name) == None,
-                                )
+                )
+            elif ignore_row_if == "either_value_is_missing":
+                selectable = (
+                    sa.select([sa.text("*")])
+                    .select_from(selectable)
+                    .where(
+                        sa.not_(
+                            sa.or_(
+                                sa.column(column_A_name) == None,
+                                sa.column(column_B_name) == None,
                             )
                         )
                     )
-                else:
-                    if ignore_row_if != "never":
-                        raise ValueError(
-                            f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
-                        )
+                )
+            else:
+                if ignore_row_if != "never":
+                    raise ValueError(
+                        f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
+                    )
 
-                return selectable
+            return selectable
 
-        if "column_list" in domain_kwargs:
-            if "ignore_row_if" in domain_kwargs:
-                if self.active_batch_data.use_quoted_name:
-                    # If case matters...
-                    column_list = [
-                        quoted_name(domain_kwargs[column_name])
-                        for column_name in domain_kwargs["column_list"]
-                    ]
-                else:
-                    column_list = domain_kwargs["column_list"]
-
-                ignore_row_if = domain_kwargs["ignore_row_if"]
-                if ignore_row_if == "all_values_are_missing":
-                    selectable = (
-                        sa.select([sa.text("*")])
-                        .select_from(selectable)
-                        .where(
-                            sa.not_(
-                                sa.and_(
-                                    *(
-                                        sa.column(column_name) == None
-                                        for column_name in column_list
-                                    )
+        if "column_list" in domain_kwargs and "ignore_row_if" in domain_kwargs:
+            if self.active_batch_data.use_quoted_name:
+                # Checking if case-sensitive and using appropriate name
+                column_list = [
+                    quoted_name(domain_kwargs[column_name])
+                    for column_name in domain_kwargs["column_list"]
+                ]
+            else:
+                column_list = domain_kwargs["column_list"]
+
+            ignore_row_if = domain_kwargs["ignore_row_if"]
+            if ignore_row_if == "all_values_are_missing":
+                selectable = (
+                    sa.select([sa.text("*")])
+                    .select_from(selectable)
+                    .where(
+                        sa.not_(
+                            sa.and_(
+                                *(
+                                    sa.column(column_name) == None
+                                    for column_name in column_list
                                 )
                             )
                         )
                     )
-                elif ignore_row_if == "any_value_is_missing":
-                    selectable = (
-                        sa.select([sa.text("*")])
-                        .select_from(selectable)
-                        .where(
-                            sa.not_(
-                                sa.or_(
-                                    *(
-                                        sa.column(column_name) == None
-                                        for column_name in column_list
-                                    )
+                )
+            elif ignore_row_if == "any_value_is_missing":
+                selectable = (
+                    sa.select([sa.text("*")])
+                    .select_from(selectable)
+                    .where(
+                        sa.not_(
+                            sa.or_(
+                                *(
+                                    sa.column(column_name) == None
+                                    for column_name in column_list
                                 )
                             )
                         )
                     )
-                else:
-                    if ignore_row_if != "never":
-                        raise ValueError(
-                            f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
-                        )
+                )
+            else:
+                if ignore_row_if != "never":
+                    raise ValueError(
+                        f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
+                    )
 
-                return selectable
+            return selectable
 
         return selectable
 
@@ -606,10 +607,9 @@ class MetricDomainTypes.
                     )
             return selectable, compute_domain_kwargs, accessor_domain_kwargs
 
-        # If user has stated they want a column, checking if one is provided, and
         elif domain_type == MetricDomainTypes.COLUMN:
             if "column" in compute_domain_kwargs:
-                # Checking if case- sensitive and using appropriate name
+                # Checking if case-sensitive and using appropriate name
                 if self.active_batch_data.use_quoted_name:
                     accessor_domain_kwargs["column"] = quoted_name(
                         compute_domain_kwargs.pop("column")
@@ -619,52 +619,54 @@ class MetricDomainTypes.
                         "column"
                     )
             else:
-                # If column not given
                 raise GreatExpectationsError(
                     "Column not provided in compute_domain_kwargs"
                 )
             return selectable, compute_domain_kwargs, accessor_domain_kwargs
 
-        # Else, if column pair values requested
         elif domain_type == MetricDomainTypes.COLUMN_PAIR:
-            # Ensuring column_A and column_B parameters provided
-            if (
+            if not (
                 "column_A" in compute_domain_kwargs
                 and "column_B" in compute_domain_kwargs
             ):
-                if self.active_batch_data.use_quoted_name:
-                    # If case matters...
-                    accessor_domain_kwargs["column_A"] = quoted_name(
-                        compute_domain_kwargs.pop("column_A")
-                    )
-                    accessor_domain_kwargs["column_B"] = quoted_name(
-                        compute_domain_kwargs.pop("column_B")
-                    )
-                else:
-                    accessor_domain_kwargs["column_A"] = compute_domain_kwargs.pop(
-                        "column_A"
-                    )
-                    accessor_domain_kwargs["column_B"] = compute_domain_kwargs.pop(
-                        "column_B"
-                    )
-            else:
                 raise GreatExpectationsError(
                     "column_A or column_B not found within compute_domain_kwargs"
                 )
+
+            # Checking if case-sensitive and using appropriate name
+            if self.active_batch_data.use_quoted_name:
+                accessor_domain_kwargs["column_A"] = quoted_name(
+                    compute_domain_kwargs.pop("column_A")
+                )
+                accessor_domain_kwargs["column_B"] = quoted_name(
+                    compute_domain_kwargs.pop("column_B")
+                )
+            else:
+                accessor_domain_kwargs["column_A"] = compute_domain_kwargs.pop(
+                    "column_A"
+                )
+                accessor_domain_kwargs["column_B"] = compute_domain_kwargs.pop(
+                    "column_B"
+                )
+
             return selectable, compute_domain_kwargs, accessor_domain_kwargs
 
-        # Checking if table or identity or other provided, column is not specified. If it is, warning the user
         elif domain_type == MetricDomainTypes.MULTICOLUMN:
-            # Ensuring column_list parameter is provided
             if "column_list" not in domain_kwargs:
                 raise GreatExpectationsError(
                     "column_list not found within domain_kwargs"
                 )
 
-            accessor_domain_kwargs["column_list"] = compute_domain_kwargs.pop(
-                "column_list"
-            )
-            # Checking if table or identity or other provided, column is not specified. If it is, warning the user
+            column_list = compute_domain_kwargs.pop("column_list")
+
+            # Checking if case-sensitive and using appropriate name
+            if self.active_batch_data.use_quoted_name:
+                accessor_domain_kwargs["column_list"] = [
+                    quoted_name(column_name) for column_name in column_list
+                ]
+            else:
+                accessor_domain_kwargs["column_list"] = column_list
+
             return selectable, compute_domain_kwargs, accessor_domain_kwargs
 
         # Letting selectable fall through
@@ -969,7 +971,7 @@ def get_batch_data_and_markers(
                         """
             )
 
-        batch_data: SqlAlchemyBatchData
+        batch_data: Optional[SqlAlchemyBatchData] = None
         batch_markers: BatchMarkers = BatchMarkers(
             {
                 "ge_load_time": datetime.datetime.now(datetime.timezone.utc).strftime(


Test patch:
diff --git a/tests/execution_engine/test_pandas_execution_engine.py b/tests/execution_engine/test_pandas_execution_engine.py
--- a/tests/execution_engine/test_pandas_execution_engine.py
+++ b/tests/execution_engine/test_pandas_execution_engine.py
@@ -58,10 +58,9 @@ def test_get_domain_records_with_column_domain():
     df = pd.DataFrame(
         {"a": [1, 2, 3, 4, 5], "b": [2, 3, 4, 5, None], "c": [1, 2, 3, 4, None]}
     )
-    expected_column_df = df.iloc[:3]
-
     # Loading batch data
     engine.load_batch_data(batch_data=df, batch_id="1234")
+
     data = engine.get_domain_records(
         domain_kwargs={
             "column": "a",
@@ -69,6 +68,9 @@ def test_get_domain_records_with_column_domain():
             "condition_parser": "pandas",
         }
     )
+
+    expected_column_df = df.iloc[:3]
+
     assert data.equals(
         expected_column_df
     ), "Data does not match after getting full access compute domain"
@@ -83,12 +85,9 @@ def test_get_domain_records_with_column_pair_domain():
             "c": [1, 2, 3, 4, 5, None],
         }
     )
-    expected_column_pair_df = pd.DataFrame(
-        {"a": [2, 3, 4, 6], "b": [3.0, 4.0, 5.0, 6.0], "c": [2.0, 3.0, 4.0, None]}
-    )
-
     # Loading batch data
     engine.load_batch_data(batch_data=df, batch_id="1234")
+
     data = engine.get_domain_records(
         domain_kwargs={
             "column_A": "a",
@@ -98,6 +97,30 @@ def test_get_domain_records_with_column_pair_domain():
             "ignore_row_if": "either_value_is_missing",
         }
     )
+
+    expected_column_pair_df = pd.DataFrame(
+        {"a": [2, 3, 4, 6], "b": [3.0, 4.0, 5.0, 6.0], "c": [2.0, 3.0, 4.0, None]}
+    )
+
+    assert data.equals(
+        expected_column_pair_df
+    ), "Data does not match after getting full access compute domain"
+
+    data = engine.get_domain_records(
+        domain_kwargs={
+            "column_A": "b",
+            "column_B": "c",
+            "row_condition": "a<6",
+            "condition_parser": "pandas",
+            "ignore_row_if": "either_value_is_missing",
+        }
+    )
+    data = data.astype(int)
+
+    expected_column_pair_df = pd.DataFrame(
+        {"a": [1, 2, 3, 4], "b": [2, 3, 4, 5], "c": [1, 2, 3, 4]}
+    )
+
     assert data.equals(
         expected_column_pair_df
     ), "Data does not match after getting full access compute domain"
@@ -112,21 +135,52 @@ def test_get_domain_records_with_multicolumn_domain():
             "c": [1, 2, 3, 4, None, 6],
         }
     )
+    # Loading batch data
+    engine.load_batch_data(batch_data=df, batch_id="1234")
+
+    data = engine.get_domain_records(
+        domain_kwargs={
+            "column_list": ["a", "c"],
+            "row_condition": "b>2",
+            "condition_parser": "pandas",
+            "ignore_row_if": "all_values_are_missing",
+        }
+    )
+    data = data.astype(int)
+
     expected_multicolumn_df = pd.DataFrame(
         {"a": [2, 3, 4, 5], "b": [3, 4, 5, 7], "c": [2, 3, 4, 6]}, index=[0, 1, 2, 4]
     )
 
+    assert data.equals(
+        expected_multicolumn_df
+    ), "Data does not match after getting full access compute domain"
+
+    engine = PandasExecutionEngine()
+    df = pd.DataFrame(
+        {
+            "a": [1, 2, 3, 4, 5, 6],
+            "b": [2, 3, 4, 5, None, 6],
+            "c": [1, 2, 3, 4, 5, None],
+        }
+    )
     # Loading batch data
     engine.load_batch_data(batch_data=df, batch_id="1234")
+
     data = engine.get_domain_records(
         domain_kwargs={
-            "column_list": ["a", "c"],
-            "row_condition": "b>2",
+            "column_list": ["b", "c"],
+            "row_condition": "a<6",
             "condition_parser": "pandas",
-            "ignore_row_if": "all_values_are_missing",
+            "ignore_row_if": "any_value_is_missing",
         }
     )
     data = data.astype(int)
+
+    expected_multicolumn_df = pd.DataFrame(
+        {"a": [1, 2, 3, 4], "b": [2, 3, 4, 5], "c": [1, 2, 3, 4]}
+    )
+
     assert data.equals(
         expected_multicolumn_df
     ), "Data does not match after getting full access compute domain"