text: from typing import Dict, Optional
  
  from great_expectations.core.expectation_configuration import ExpectationConfiguration
  from great_expectations.execution_engine import ExecutionEngine
  from great_expectations.expectations.expectation import ColumnExpectation
  from great_expectations.expectations.util import render_evaluation_parameter_string
  from great_expectations.render.renderer.renderer import renderer
  from great_expectations.render.types import RenderedStringTemplateContent
  from great_expectations.render.util import (
      handle_strict_min_max,
      parse_row_condition_string_pandas_engine,
      substitute_none_for_missing,
  )
  
  
  class ExpectColumnMedianToBeBetween(ColumnExpectation):
      """Expect the column median to be between a minimum value and a maximum value.
  
              expect_column_median_to_be_between is a \
              :func:`column_aggregate_expectation \
              <great_expectations.execution_engine.execution_engine.MetaExecutionEngine.column_aggregate_expectation>`.
  
              Args:
                  column (str): \
                      The column name.
                  min_value (int or None): \
                      The minimum value for the column median.
                  max_value (int or None): \
                      The maximum value for the column median.
                  strict_min (boolean):
                      If True, the column median must be strictly larger than min_value, default=False
                  strict_max (boolean):
                      If True, the column median must be strictly smaller than max_value, default=False
  
              Other Parameters:
                  result_format (str or None): \
                      Which output mode to use: `BOOLEAN_ONLY`, `BASIC`, `COMPLETE`, or `SUMMARY`.
                      For more detail, see :ref:`result_format <result_format>`.
                  include_config (boolean): \
                      If True, then include the expectation config as part of the result object. \
                      For more detail, see :ref:`include_config`.
                  catch_exceptions (boolean or None): \
                      If True, then catch exceptions and include them as part of the result object. \
                      For more detail, see :ref:`catch_exceptions`.
                  meta (dict or None): \
                      A JSON-serializable dictionary (nesting allowed) that will be included in the output without \
                      modification. For more detail, see :ref:`meta`.
  
              Returns:
                  An ExpectationSuiteValidationResult
  
                  Exact fields vary depending on the values passed to :ref:`result_format <result_format>` and
                  :ref:`include_config`, :ref:`catch_exceptions`, and :ref:`meta`.
  
              Notes:
                  These fields in the result object are customized for this expectation:
                  ::
  
                      {
                          "observed_value": (float) The true median for the column
                      }
  
                  * min_value and max_value are both inclusive unless strict_min or strict_max are set to True.
                  * If min_value is None, then max_value is treated as an upper bound
                  * If max_value is None, then min_value is treated as a lower bound
  
              See Also:
                  :func:`expect_column_mean_to_be_between \
                  <great_expectations.execution_engine.execution_engine.ExecutionEngine.expect_column_mean_to_be_between>`
  
                  :func:`expect_column_stdev_to_be_between \
                  <great_expectations.execution_engine.execution_engine.ExecutionEngine.expect_column_stdev_to_be_between>`
  
              """
  
      # This dictionary contains metadata for display in the public gallery
      library_metadata = {
          "maturity": "production",
          "tags": ["core expectation", "column aggregate expectation"],
          "contributors": ["@great_expectations"],
          "requirements": [],
          "has_full_test_suite": True,
          "manually_reviewed_code": True,
      }
  
      # Setting necessary computation metric dependencies and defining kwargs, as well as assigning kwargs default values\
      metric_dependencies = ("column.median",)
      success_keys = ("min_value", "strict_min", "max_value", "strict_max")
  
      # Default values
      default_kwarg_values = {
          "min_value": None,
          "max_value": None,
          "strict_min": None,
          "strict_max": None,
          "result_format": "BASIC",
          "include_config": True,
          "catch_exceptions": False,
      }
      args_keys = (
          "column",
          "min_value",
          "max_value",
          "strict_min",
          "strict_max",
      )
  
      def validate_configuration(
          self, configuration: Optional[ExpectationConfiguration]
      ) -> None:
          """
          Validates that a configuration has been set, and sets a configuration if it has yet to be set. Ensures that
          necessary configuration arguments have been provided for the validation of the expectation.
  
          Args:
              configuration (OPTIONAL[ExpectationConfiguration]): \
                  An optional Expectation Configuration entry that will be used to configure the expectation
          Returns:
              None. Raises InvalidExpectationConfigurationError if the config is not validated successfully
          """
          super().validate_configuration(configuration)
          self.validate_metric_value_between_configuration(configuration=configuration)
  
      @classmethod
      def _atomic_prescriptive_template(
          cls,
          configuration=None,
          result=None,
          language=None,
          runtime_configuration=None,
          **kwargs,
      ):
          runtime_configuration = runtime_configuration or {}
          include_column_name = runtime_configuration.get("include_column_name", True)
          include_column_name = (
              include_column_name if include_column_name is not None else True
          )
          styling = runtime_configuration.get("styling")
          params = substitute_none_for_missing(
              configuration.kwargs,
              [
                  "column",
                  "min_value",
                  "max_value",
                  "row_condition",
                  "condition_parser",
                  "strict_min",
                  "strict_max",
              ],
          )
          params_with_json_schema = {
              "column": {"schema": {"type": "string"}, "value": params.get("column")},
              "min_value": {
                  "schema": {"type": "number"},
                  "value": params.get("min_value"),
              },
              "max_value": {
                  "schema": {"type": "number"},
                  "value": params.get("max_value"),
              },
              "row_condition": {
                  "schema": {"type": "string"},
                  "value": params.get("row_condition"),
              },
              "condition_parser": {
                  "schema": {"type": "string"},
                  "value": params.get("condition_parser"),
              },
              "strict_min": {
                  "schema": {"type": "boolean"},
                  "value": params.get("strict_min"),
              },
              "strict_max": {
                  "schema": {"type": "boolean"},
                  "value": params.get("strict_max"),
              },
          }
  
          if (params["min_value"] is None) and (params["max_value"] is None):
              template_str = "median may have any numerical value."
          else:
              at_least_str, at_most_str = handle_strict_min_max(params)
              if params["min_value"] is not None and params["max_value"] is not None:
                  template_str = f"median must be {at_least_str} $min_value and {at_most_str} $max_value."
              elif params["min_value"] is None:
                  template_str = f"median must be {at_most_str} $max_value."
              elif params["max_value"] is None:
                  template_str = f"median must be {at_least_str} $min_value."
  
          if include_column_name:
              template_str = f"$column {template_str}"
  
          if params["row_condition"] is not None:
              (
                  conditional_template_str,
                  conditional_params,
              ) = parse_row_condition_string_pandas_engine(
                  params["row_condition"], with_schema=True
              )
              template_str = f"{conditional_template_str}, then {template_str}"
              params_with_json_schema.update(conditional_params)
  
          return (template_str, params_with_json_schema, styling)
  
      @classmethod
      @renderer(renderer_type="renderer.prescriptive")
      @render_evaluation_parameter_string
      def _prescriptive_renderer(
          cls,
          configuration=None,
          result=None,
          language=None,
          runtime_configuration=None,
          **kwargs,
      ):
          runtime_configuration = runtime_configuration or {}
          include_column_name = runtime_configuration.get("include_column_name", True)
          include_column_name = (
              include_column_name if include_column_name is not None else True
          )
          styling = runtime_configuration.get("styling")
          params = substitute_none_for_missing(
              configuration.kwargs,
              [
                  "column",
                  "min_value",
                  "max_value",
                  "row_condition",
                  "condition_parser",
                  "strict_min",
                  "strict_max",
              ],
          )
  
          if (params["min_value"] is None) and (params["max_value"] is None):
              template_str = "median may have any numerical value."
          else:
              at_least_str, at_most_str = handle_strict_min_max(params)
              if params["min_value"] is not None and params["max_value"] is not None:
                  template_str = f"median must be {at_least_str} $min_value and {at_most_str} $max_value."
              elif params["min_value"] is None:
                  template_str = f"median must be {at_most_str} $max_value."
              elif params["max_value"] is None:
                  template_str = f"median must be {at_least_str} $min_value."
  
          if include_column_name:
              template_str = f"$column {template_str}"
  
          if params["row_condition"] is not None:
              (
                  conditional_template_str,
                  conditional_params,
              ) = parse_row_condition_string_pandas_engine(params["row_condition"])
              template_str = f"{conditional_template_str}, then {template_str}"
              params.update(conditional_params)
  
          return [
              RenderedStringTemplateContent(
                  **{
                      "content_block_type": "string_template",
                      "string_template": {
                          "template": template_str,
                          "params": params,
                          "styling": styling,
                      },
                  }
              )
          ]
  
      def _validate(
          self,
          configuration: ExpectationConfiguration,
          metrics: Dict,
          runtime_configuration: dict = None,
          execution_engine: ExecutionEngine = None,
      ):
          return self._validate_metric_value_between(
              metric_name="column.median",
              configuration=configuration,
              metrics=metrics,
              runtime_configuration=runtime_configuration,
              execution_engine=execution_engine,
          )
  