class_docstr: Builds a dataflow plan to satisfy a given query.
class_docstr_tok: ["Builds","a","dataflow","plan","to","satisfy","a","given","query","."]
docstr: Ensures that the group of MeasureSpecs has the same non_additive_dimension_spec and agg_time_dimension.
docstr_tok: ["Ensures","that","the","group","of","MeasureSpecs","has","the","same","non_additive_dimension_spec","and","agg_time_dimension","."]
code: def _build_measure_spec_properties(
      self, measure_specs: Sequence[MeasureSpec]
  ) -> MeasureSpecProperties:
      """Ensures that the group of MeasureSpecs has the same non_additive_dimension_spec and agg_time_dimension."""
      if len(measure_specs) == 0:
          raise ValueError(
              "Cannot build MeasureParametersForRecipe when given an empty sequence of measure_specs."
          )
      semantic_models = self._get_semantic_model_names_for_measures(
          measure_specs
      )
      if len(semantic_models) > 1:
          raise ValueError(
              f"Cannot find common properties for measures {measure_specs} coming from multiple "
              f"semantic models: {semantic_models}. This suggests the measure_specs were not correctly filtered."
          )
  
      agg_time_dimension = (
          agg_time_dimension
      ) = self._semantic_model_lookup.get_agg_time_dimension_for_measure(
          measure_specs[0].reference
      )
      non_additive_dimension_spec = measure_specs[
          0
      ].non_additive_dimension_spec
      for measure_spec in measure_specs:
          if (
              non_additive_dimension_spec
              != measure_spec.non_additive_dimension_spec
          ):
              raise ValueError(
                  f"measure_specs {measure_specs} do not have the same non_additive_dimension_spec."
              )
          measure_agg_time_dimension = self._semantic_model_lookup.get_agg_time_dimension_for_measure(
              measure_spec.reference
          )
          if measure_agg_time_dimension != agg_time_dimension:
              raise ValueError(
                  f"measure_specs {measure_specs} do not have the same agg_time_dimension."
              )
      return MeasureSpecProperties(
          measure_specs=measure_specs,
          semantic_model_name=semantic_models.pop(),
          agg_time_dimension=agg_time_dimension,
          non_additive_dimension_spec=non_additive_dimension_spec,
      )
  
imports: from __future__ import annotations
  import logging
  import time
  from dataclasses import dataclass
  from typing import Dict, List, Optional, Sequence, Set, Tuple, Union
  from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
  from dbt_semantic_interfaces.implementations.metric import PydanticMetricTimeWindow
  from dbt_semantic_interfaces.pretty_print import pformat_big_objects
  from dbt_semantic_interfaces.protocols.metric import ConstantPropertyInput, ConversionTypeParams, MetricInputMeasure, MetricTimeWindow, MetricType
  from dbt_semantic_interfaces.references import MeasureReference, MetricReference, TimeDimensionReference
  from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
  from dbt_semantic_interfaces.validations.unique_valid_name import MetricFlowReservedKeywords
  from metricflow.dag.id_generation import DATAFLOW_PLAN_PREFIX, IdGeneratorRegistry
  from metricflow.dataflow.builder.node_data_set import DataflowPlanNodeOutputDataSetResolver
  from metricflow.dataflow.builder.node_evaluator import JoinLinkableInstancesRecipe, LinkableInstanceSatisfiabilityEvaluation, NodeEvaluatorForLinkableInstances
  from metricflow.dataflow.dataflow_plan import AddGeneratedUuidColumnNode, AggregateMeasuresNode, BaseOutput, CombineAggregatedOutputsNode, ComputeMetricsNode, ConstrainTimeRangeNode, DataflowPlan, FilterElementsNode, JoinConversionEventsNode, JoinDescription, JoinOverTimeRangeNode, JoinToBaseOutputNode, JoinToTimeSpineNode, MinMaxNode, OrderByLimitNode, ReadSqlSourceNode, SemiAdditiveJoinNode, SinkOutput, WhereConstraintNode, WriteToResultDataframeNode, WriteToResultTableNode
  from metricflow.dataflow.dataflow_plan_to_text import dataflow_dag_as_text
  from metricflow.dataflow.optimizer.dataflow_plan_optimizer import DataflowPlanOptimizer
  from metricflow.dataflow.sql_table import SqlTable
  from metricflow.dataset.dataset import DataSet
  from metricflow.errors.errors import UnableToSatisfyQueryError
  from metricflow.filters.time_constraint import TimeRangeConstraint
  from metricflow.mf_logging.pretty_print import mf_pformat
  from metricflow.mf_logging.runtime import log_runtime
  from metricflow.model.semantic_manifest_lookup import SemanticManifestLookup
  from metricflow.plan_conversion.column_resolver import DunderColumnAssociationResolver
  from metricflow.plan_conversion.node_processor import PreJoinNodeProcessor
  from metricflow.query.group_by_item.filter_spec_resolution.filter_location import WhereFilterLocation
  from metricflow.query.group_by_item.filter_spec_resolution.filter_spec_lookup import FilterSpecResolutionLookUp
  from metricflow.specs.column_assoc import ColumnAssociationResolver
  from metricflow.specs.specs import ConstantPropertySpec, CumulativeMeasureDescription, EntitySpec, InstanceSpecSet, JoinToTimeSpineDescription, LinkableInstanceSpec, LinkableSpecSet, LinklessEntitySpec, MeasureSpec, MetadataSpec, MetricFlowQuerySpec, MetricInputMeasureSpec, MetricSpec, NonAdditiveDimensionSpec, OrderBySpec, TimeDimensionSpec, WhereFilterSpec
  from metricflow.specs.where_filter_transform import WhereSpecFactory
  from metricflow.sql.sql_plan import SqlJoinType
label_desc: Use image node_id 19 for calling the DataflowPlanBuilder obj's underlying member method code with example usage: obj._build_measure_spec_properties(measure_specs) and returns: MeasureSpecProperties