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/exceptions/exceptions.py b/great_expectations/exceptions/exceptions.py
--- a/great_expectations/exceptions/exceptions.py
+++ b/great_expectations/exceptions/exceptions.py
@@ -120,13 +120,13 @@ class ProfilerError(GreatExpectationsError):
 
 
 class ProfilerConfigurationError(ProfilerError):
-    """A configuration error for a profiler."""
+    """A configuration error for a "RuleBasedProfiler" class."""
 
     pass
 
 
 class ProfilerExecutionError(ProfilerError):
-    """A runtime error for a profiler."""
+    """A runtime error for a "RuleBasedProfiler" class."""
 
     pass
 
@@ -135,6 +135,16 @@ class ProfilerNotFoundError(ProfilerError):
     pass
 
 
+class DataAssistantError(ProfilerError):
+    pass
+
+
+class DataAssistantExecutionError(DataAssistantError):
+    """A runtime error for a "DataAssistant" class."""
+
+    pass
+
+
 class InvalidConfigError(DataContextError):
     def __init__(self, message) -> None:
         self.message = message
diff --git a/great_expectations/rule_based_profiler/data_assistant/data_assistant.py b/great_expectations/rule_based_profiler/data_assistant/data_assistant.py
--- a/great_expectations/rule_based_profiler/data_assistant/data_assistant.py
+++ b/great_expectations/rule_based_profiler/data_assistant/data_assistant.py
@@ -3,6 +3,9 @@
 from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union
 
 from great_expectations.core.batch import Batch, BatchRequestBase
+from great_expectations.core.usage_statistics.usage_statistics import (
+    UsageStatisticsHandler,
+)
 from great_expectations.rule_based_profiler import RuleBasedProfilerResult
 from great_expectations.rule_based_profiler.config import ParameterBuilderConfig
 from great_expectations.rule_based_profiler.domain_builder import (
@@ -447,10 +450,20 @@ def run(
         Returns:
             DataAssistantResult: The result object for the DataAssistant
         """
+        usage_statistics_handler: Optional[UsageStatisticsHandler]
+        if self._data_context is None:
+            usage_statistics_handler = None
+        else:
+            usage_statistics_handler = self._data_context._usage_statistics_handler
+
+        batches: Dict[str, Batch] = self._batches
+        if batches is None:
+            batches = {}
+
         data_assistant_result: DataAssistantResult = DataAssistantResult(
             batch_id_to_batch_identifier_display_name_map=self.batch_id_to_batch_identifier_display_name_map(),
             execution_time=0.0,
-            usage_statistics_handler=self._data_context._usage_statistics_handler,
+            usage_statistics_handler=usage_statistics_handler,
         )
         run_profiler_on_data(
             data_assistant=self,
@@ -458,7 +471,7 @@ def run(
             profiler=self.profiler,
             variables=variables,
             rules=rules,
-            batch_list=list(self._batches.values()),
+            batch_list=list(batches.values()),
             batch_request=None,
             variables_directives_list=variables_directives_list,
             domain_type_directives_list=domain_type_directives_list,
@@ -592,11 +605,15 @@ def batch_id_to_batch_identifier_display_name_map(
         """
         This method uses loaded "Batch" objects to return the mapping between unique "batch_id" and "batch_identifiers".
         """
+        batches: Dict[str, Batch] = self._batches
+        if batches is None:
+            batches = {}
+
         batch_id: str
         batch: Batch
         return {
             batch_id: set(batch.batch_definition.batch_identifiers.items())
-            for batch_id, batch in self._batches.items()
+            for batch_id, batch in batches.items()
         }
 
 
diff --git a/great_expectations/rule_based_profiler/data_assistant/data_assistant_runner.py b/great_expectations/rule_based_profiler/data_assistant/data_assistant_runner.py
--- a/great_expectations/rule_based_profiler/data_assistant/data_assistant_runner.py
+++ b/great_expectations/rule_based_profiler/data_assistant/data_assistant_runner.py
@@ -3,6 +3,7 @@
 from inspect import Signature, signature
 from typing import Any, Callable, Dict, List, Optional, Type, Union
 
+import great_expectations.exceptions as ge_exceptions
 from great_expectations.core.batch import BatchRequestBase
 from great_expectations.core.config_peer import ConfigOutputModes, ConfigOutputModeType
 from great_expectations.data_context.types.base import BaseYamlConfig
@@ -191,6 +192,13 @@ def run(
         Returns:
             DataAssistantResult: The result object for the DataAssistant
         """
+        if batch_request is None:
+            data_assistant_name: str = self._data_assistant_cls.data_assistant_type
+            raise ge_exceptions.DataAssistantExecutionError(
+                message=f"""Utilizing "{data_assistant_name}.run()" requires valid "batch_request" to be \
+specified (empty or missing "batch_request" detected)."""
+            )
+
         data_assistant: DataAssistant = self._build_data_assistant(
             batch_request=batch_request
         )


Test patch: