metricflow 0.206.0.dev2__tar.gz → 0.206.0.dev3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/PKG-INFO +5 -5
- metricflow-0.206.0.dev3/metricflow/data_table/column_types.py +22 -0
- metricflow-0.206.0.dev3/metricflow/data_table/mf_column.py +39 -0
- metricflow-0.206.0.dev3/metricflow/data_table/mf_table.py +274 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/builder/dataflow_plan_builder.py +229 -164
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/builder/measure_additiveness.py +1 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/builder/node_data_set.py +9 -6
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/builder/node_evaluator.py +49 -41
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/builder/partitions.py +7 -6
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/builder/source_node.py +27 -11
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/dataflow_plan.py +65 -70
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/add_generated_uuid.py +10 -7
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/aggregate_measures.py +8 -17
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/combine_aggregated_outputs.py +8 -7
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/compute_metrics.py +35 -11
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/constrain_time.py +10 -9
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/filter_elements.py +12 -11
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/join_conversion_events.py +15 -9
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/join_over_time.py +10 -10
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/join_to_base.py +15 -14
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/join_to_time_spine.py +11 -11
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/metric_time_transform.py +8 -8
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/min_max.py +8 -7
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/order_by_limit.py +9 -10
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/read_sql_source.py +15 -7
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/semi_additive_join.py +9 -9
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/where_filter.py +9 -9
- metricflow-0.206.0.dev2/metricflow/dataflow/nodes/write_to_dataframe.py → metricflow-0.206.0.dev3/metricflow/dataflow/nodes/write_to_data_table.py +14 -17
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/nodes/write_to_table.py +8 -13
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/optimizer/source_scan/cm_branch_combiner.py +26 -15
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/optimizer/source_scan/matching_linkable_specs.py +1 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/optimizer/source_scan/source_scan_optimizer.py +33 -70
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataset/convert_semantic_model.py +12 -12
- metricflow-0.206.0.dev2/metricflow/dataset/dataset.py → metricflow-0.206.0.dev3/metricflow/dataset/dataset_classes.py +2 -3
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataset/semantic_model_adapter.py +1 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataset/sql_dataset.py +29 -23
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/engine/metricflow_engine.py +89 -110
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/engine/models.py +8 -11
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/engine/time_source.py +1 -1
- metricflow-0.206.0.dev3/metricflow/execution/dataflow_to_execution.py +184 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/execution/execution_plan.py +9 -9
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/execution/executor.py +2 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/context/snowflake.py +41 -16
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/convert_to_sql_plan.py +2 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/dataflow_to_sql.py +76 -60
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/instance_converters.py +35 -28
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/node_processor.py +192 -34
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/spec_transforms.py +3 -5
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/sql_join_builder.py +3 -2
- metricflow-0.206.0.dev3/metricflow/plan_conversion/time_spine.py +55 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/protocols/sql_client.py +4 -4
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/optimizer/rewriting_sub_query_reducer.py +2 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/big_query.py +2 -2
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/databricks.py +1 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/duckdb_renderer.py +1 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/expr_renderer.py +2 -2
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/postgres.py +2 -2
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/redshift.py +2 -2
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/snowflake.py +7 -3
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/sql_plan_renderer.py +3 -2
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/trino.py +1 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/sql_exprs.py +4 -5
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/sql_plan.py +4 -19
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/telemetry/handlers/python_log.py +2 -1
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/telemetry/reporter.py +1 -1
- {metricflow-0.206.0.dev2/metricflow/model → metricflow-0.206.0.dev3/metricflow/validation}/data_warehouse_model_validator.py +13 -10
- metricflow-0.206.0.dev3/metricflow/validation/dataflow_join_validator.py +75 -0
- metricflow-0.206.0.dev3/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py +75 -0
- metricflow-0.206.0.dev3/metricflow_semantics/collection_helpers/dedupe.py +15 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/dag/dag_to_text.py +2 -2
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/dag/dag_visualization.py +2 -2
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/dag/id_prefix.py +2 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/dag/mf_dag.py +4 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/dag/sequential_id.py +1 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/filters/time_constraint.py +0 -35
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/instances.py +4 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/mf_logging/pretty_print.py +12 -5
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/dbt_manifest_parser.py +1 -1
- metricflow-0.206.0.dev2/metricflow/model/semantics/linkable_element_properties.py → metricflow-0.206.0.dev3/metricflow_semantics/model/linkable_element_property.py +9 -8
- metricflow-0.206.0.dev3/metricflow_semantics/model/semantic_manifest_lookup.py +31 -0
- metricflow-0.206.0.dev3/metricflow_semantics/model/semantic_model_derivation.py +24 -0
- metricflow-0.206.0.dev3/metricflow_semantics/model/semantics/linkable_element.py +378 -0
- metricflow-0.206.0.dev3/metricflow_semantics/model/semantics/linkable_element_set.py +417 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/semantics/linkable_spec_resolver.py +242 -494
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/semantics/metric_lookup.py +69 -73
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/semantics/semantic_model_join_evaluator.py +4 -41
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/semantics/semantic_model_lookup.py +79 -88
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/spec_converters.py +1 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/naming/dunder_scheme.py +8 -7
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/naming/metric_scheme.py +5 -5
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/naming/naming_scheme.py +2 -2
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/naming/object_builder_scheme.py +6 -6
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/naming/object_builder_str.py +3 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/protocols/query_parameter.py +1 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/candidate_push_down/group_by_item_candidate.py +46 -23
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/candidate_push_down/push_down_visitor.py +90 -90
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/filter_spec_resolution/filter_pattern_factory.py +2 -2
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/filter_spec_resolution/filter_spec_lookup.py +84 -17
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/filter_spec_resolution/filter_spec_resolver.py +20 -18
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/group_by_item_resolver.py +49 -29
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/path_prefixable.py +1 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_dag/dag.py +5 -5
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_dag/dag_builder.py +7 -7
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_dag/input_metric_location.py +1 -1
- metricflow-0.206.0.dev3/metricflow_semantics/query/group_by_item/resolution_dag/resolution_nodes/base_node.py +112 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_dag/resolution_nodes/measure_source_node.py +9 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_dag/resolution_nodes/metric_resolution_node.py +11 -6
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_dag/resolution_nodes/no_metrics_query_source_node.py +9 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_dag/resolution_nodes/query_resolution_node.py +11 -6
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/resolution_path.py +3 -3
- metricflow-0.206.0.dev3/metricflow_semantics/query/issues/__init__.py +0 -0
- metricflow-0.206.0.dev3/metricflow_semantics/query/issues/filter_spec_resolver/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/filter_spec_resolver/invalid_where.py +4 -4
- metricflow-0.206.0.dev3/metricflow_semantics/query/issues/group_by_item_resolver/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/group_by_item_resolver/ambiguous_group_by_item.py +7 -7
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/group_by_item_resolver/invalid_use_of_date_part.py +5 -5
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/group_by_item_resolver/multiple_join_paths.py +7 -7
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/group_by_item_resolver/no_common_items.py +8 -8
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/group_by_item_resolver/no_matching_items_for_measure.py +5 -5
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/group_by_item_resolver/no_matching_items_for_no_metrics_query.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/group_by_item_resolver/no_parent_candidates.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/issues_base.py +4 -4
- metricflow-0.206.0.dev3/metricflow_semantics/query/issues/parsing/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/cumulative_metric_requires_metric_time.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/duplicate_metric.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/invalid_limit.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/invalid_metric.py +5 -5
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/invalid_min_max_only.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/invalid_order.py +4 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/no_metric_or_group_by.py +4 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/offset_metric_requires_metric_time.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/issues/parsing/string_input_parsing_issue.py +3 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/query_parser.py +71 -58
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/query_resolution.py +20 -10
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/query_resolver.py +118 -32
- metricflow-0.206.0.dev3/metricflow_semantics/query/resolver_inputs/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/resolver_inputs/base_resolver_inputs.py +2 -2
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/resolver_inputs/query_resolver_inputs.py +12 -9
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/similarity.py +5 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/suggestion_generator.py +15 -9
- metricflow-0.206.0.dev3/metricflow_semantics/query/validation_rules/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/validation_rules/base_validation_rule.py +4 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/validation_rules/duplicate_metric.py +6 -6
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/validation_rules/metric_time_requirements.py +10 -8
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/validation_rules/query_validator.py +13 -13
- metricflow-0.206.0.dev3/metricflow_semantics/specs/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/column_assoc.py +1 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/dimension_spec_resolver.py +1 -1
- metricflow-0.206.0.dev2/metricflow/plan_conversion/column_resolver.py → metricflow-0.206.0.dev3/metricflow_semantics/specs/dunder_column_association_resolver.py +26 -46
- metricflow-0.206.0.dev3/metricflow_semantics/specs/linkable_spec_set.py +161 -0
- metricflow-0.206.0.dev3/metricflow_semantics/specs/partition_spec_set.py +16 -0
- metricflow-0.206.0.dev3/metricflow_semantics/specs/patterns/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/base_time_grain.py +5 -6
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/entity_link_pattern.py +8 -3
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/match_list_pattern.py +2 -2
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/metric_pattern.py +4 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/metric_time_pattern.py +4 -5
- metricflow-0.206.0.dev3/metricflow_semantics/specs/patterns/no_group_by_metric.py +29 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/none_date_part.py +5 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/spec_pattern.py +1 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/patterns/typed_patterns.py +27 -10
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/python_object.py +4 -4
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/query_param_implementations.py +7 -7
- metricflow-0.206.0.dev3/metricflow_semantics/specs/query_spec.py +62 -0
- metricflow-0.206.0.dev3/metricflow_semantics/specs/rendered_spec_tracker.py +30 -0
- metricflow-0.206.0.dev2/metricflow/specs/specs.py → metricflow-0.206.0.dev3/metricflow_semantics/specs/spec_classes.py +173 -426
- metricflow-0.206.0.dev3/metricflow_semantics/specs/spec_set.py +213 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/spec_set_transforms.py +3 -1
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/where_filter_dimension.py +12 -11
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/where_filter_entity.py +13 -11
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/where_filter_metric.py +13 -11
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/where_filter_time_dimension.py +14 -12
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/specs/where_filter_transform.py +19 -11
- metricflow-0.206.0.dev3/metricflow_semantics/sql/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/sql/sql_bind_parameters.py +2 -2
- metricflow-0.206.0.dev3/metricflow_semantics/sql/sql_join_type.py +18 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/__init__.py +0 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/config_helpers.py +47 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/example_project_configuration.py +35 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/id_helpers.py +54 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/manifest_helpers.py +26 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/metric_time_dimension.py +26 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/ambiguous_resolution_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/ambiguous_resolution_manifest/metrics.yaml +93 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/ambiguous_resolution_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/ambiguous_resolution_manifest/semantic_models/monthly_measures_source.yaml +25 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/ambiguous_resolution_manifest/semantic_models/yearly_measures_source.yaml +23 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/config_linter_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/config_linter_manifest/multiple_semantic_models_without_divider.yml +42 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/config_linter_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/cyclic_join_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/cyclic_join_manifest/listings_latest.yaml +35 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/cyclic_join_manifest/listings_latest_cyclic.yaml +21 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/cyclic_join_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/data_warehouse_validation_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/data_warehouse_validation_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/data_warehouse_validation_manifest/semantic_models/semantic_model1.yml +31 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/metrics/bookings_cumulative.yaml +7 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/metrics/bookings_last_month.yaml +10 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/metrics/bookings_monthly_cumulative.yaml +7 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/semantic_models/bookings_monthly_source.yaml +30 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/semantic_models/extended_bookings_source.yaml +35 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/extended_date_manifest/semantic_models/listings_extended_source.yaml +20 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/join_types_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/join_types_manifest/bookings_source.yaml +29 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/join_types_manifest/listings_source.yaml +17 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/join_types_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/multi_hop_join_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/multi_hop_join_manifest/account_month_txns.yaml +28 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/multi_hop_join_manifest/bridge_table.yaml +18 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/multi_hop_join_manifest/customer_other_data.yaml +18 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/multi_hop_join_manifest/customer_table.yaml +18 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/multi_hop_join_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/multi_hop_join_manifest/third_hop_table.yaml +16 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/non_sm_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/non_sm_manifest/bookings_source.yaml +32 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/non_sm_manifest/listings_latest.yaml +35 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/non_sm_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/account_month_txns.yaml +33 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/bridge_table.yaml +34 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/customer_other_data.yaml +30 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/customer_table.yaml +33 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/metrics.yaml +8 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/partitioned_multi_hop_join_manifest/third_hop_table.yaml +29 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/scd_accounts.yaml +33 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/scd_bookings.yaml +66 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/scd_companies.yaml +20 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/scd_listings.yaml +40 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/scd_lux_listings.yaml +49 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/scd_metrics.yaml +25 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/scd_manifest/scd_users.yaml +21 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/shared/project_configuration.yaml +7 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/metrics.yaml +774 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/saved_queries.yaml +24 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/accounts_source.yaml +46 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/bookings_source.yaml +98 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/buys_source.yaml +34 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/companies.yaml +20 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/id_verifications.yaml +37 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/listings_latest.yaml +50 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/lux_listing_mapping.yaml +16 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/revenue.yaml +30 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/user_sm_source.yaml +30 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/users_latest.yaml +22 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/views_source.yaml +37 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/semantic_models/visits_source.yaml +37 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/__init__.py +5 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/all_entity_measure_source.yaml +33 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/entity_0_dimension_source.yaml +16 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/entity_0_measure_source.yaml +25 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/entity_1_and_entity_2_measure_source.yaml +31 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/entity_1_dimension_source.yaml +16 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/entity_1_measure_source.yaml +25 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/entity_1_to_entity_0_mapping_source.yaml +14 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/entity_2_to_entity_0_mapping_source.yaml +14 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/metrics.yaml +28 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_multi_hop_join_manifest/project_configuration.yaml +1 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/snapshot_helpers.py +392 -0
- metricflow-0.206.0.dev3/metricflow_semantics/test_helpers/time_helpers.py +19 -0
- metricflow-0.206.0.dev3/metricflow_semantics/time/__init__.py +0 -0
- metricflow-0.206.0.dev3/metricflow_semantics/time/dateutil_adjuster.py +114 -0
- metricflow-0.206.0.dev3/metricflow_semantics/time/time_period.py +47 -0
- metricflow-0.206.0.dev3/metricflow_semantics/workarounds/__init__.py +4 -0
- metricflow-0.206.0.dev3/metricflow_semantics/workarounds/reference.py +12 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/pyproject.toml +26 -19
- metricflow-0.206.0.dev2/.gitattributes +0 -1
- metricflow-0.206.0.dev2/CHANGELOG.md +0 -516
- metricflow-0.206.0.dev2/GLOSSARY.md +0 -13
- metricflow-0.206.0.dev2/TENETS.md +0 -12
- metricflow-0.206.0.dev2/assets/MetricFlow_logo.png +0 -0
- metricflow-0.206.0.dev2/assets/example_plan.svg +0 -219
- metricflow-0.206.0.dev2/metricflow/mf_logging/__init__.py +0 -4
- metricflow-0.206.0.dev2/metricflow/model/semantic_manifest_lookup.py +0 -59
- metricflow-0.206.0.dev2/metricflow/plan_conversion/dataflow_to_execution.py +0 -102
- metricflow-0.206.0.dev2/metricflow/plan_conversion/time_spine.py +0 -29
- metricflow-0.206.0.dev2/metricflow/protocols/semantics.py +0 -227
- metricflow-0.206.0.dev2/metricflow/query/group_by_item/resolution_dag/resolution_nodes/base_node.py +0 -67
- metricflow-0.206.0.dev2/metricflow/specs/rendered_spec_tracker.py +0 -24
- metricflow-0.206.0.dev2/metricflow/test_helpers.py +0 -204
- metricflow-0.206.0.dev2/metricflow/time/time_granularity.py +0 -169
- metricflow-0.206.0.dev2/mypy.ini +0 -55
- metricflow-0.206.0.dev2/ruff.toml +0 -84
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/.gitignore +0 -0
- /metricflow-0.206.0.dev2/attribution.md → /metricflow-0.206.0.dev3/ATTRIBUTION.md +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/LICENSE +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/README.md +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/collection_helpers → metricflow-0.206.0.dev3/metricflow/data_table}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/dag → metricflow-0.206.0.dev3/metricflow/dataflow}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/dataflow → metricflow-0.206.0.dev3/metricflow/dataflow/builder}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/dataflow/builder → metricflow-0.206.0.dev3/metricflow/dataflow/nodes}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/dataflow/nodes → metricflow-0.206.0.dev3/metricflow/dataflow/optimizer}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/dataflow/optimizer/dataflow_plan_optimizer.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/dataflow/optimizer → metricflow-0.206.0.dev3/metricflow/dataflow/optimizer/source_scan}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/dataflow/optimizer/source_scan → metricflow-0.206.0.dev3/metricflow/dataset}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/dataset → metricflow-0.206.0.dev3/metricflow/engine}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/engine → metricflow-0.206.0.dev3/metricflow/execution}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/plan_conversion → metricflow-0.206.0.dev3/metricflow/execution}/convert_to_execution_plan.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/errors → metricflow-0.206.0.dev3/metricflow/inference}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/execution → metricflow-0.206.0.dev3/metricflow/inference/context}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/context/base.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/context/data_warehouse.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/models.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/filters → metricflow-0.206.0.dev3/metricflow/inference/renderer}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/renderer/base.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/renderer/config_file.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/renderer/stream.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/inference → metricflow-0.206.0.dev3/metricflow/inference/rule}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/rule/base.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/rule/defaults.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/rule/rules.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/runner.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/inference/context → metricflow-0.206.0.dev3/metricflow/inference/solver}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/solver/base.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/inference/solver/weighted_tree.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/inference/renderer → metricflow-0.206.0.dev3/metricflow/plan_conversion}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/select_column_gen.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/plan_conversion/sql_expression_builders.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/inference/solver → metricflow-0.206.0.dev3/metricflow/protocols}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/py.typed +0 -0
- {metricflow-0.206.0.dev2/metricflow/model → metricflow-0.206.0.dev3/metricflow/sql}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/model/semantics → metricflow-0.206.0.dev3/metricflow/sql/optimizer}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/optimizer/column_pruner.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/optimizer/optimization_levels.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/optimizer/sql_query_plan_optimizer.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/optimizer/sub_query_reducer.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/optimizer/table_alias_simplifier.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/model/transformations → metricflow-0.206.0.dev3/metricflow/sql/render}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/render/rendering_constants.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/sql_column.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql/sql_table.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/naming → metricflow-0.206.0.dev3/metricflow/sql_request}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/sql_request/sql_request_attributes.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/plan_conversion → metricflow-0.206.0.dev3/metricflow/telemetry}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/protocols → metricflow-0.206.0.dev3/metricflow/telemetry/handlers}/__init__.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/telemetry/handlers/handlers.py +0 -0
- {metricflow-0.206.0.dev2 → metricflow-0.206.0.dev3}/metricflow/telemetry/models.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query → metricflow-0.206.0.dev3/metricflow/validation}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/group_by_item → metricflow-0.206.0.dev3/metricflow_semantics}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/aggregation_properties.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/group_by_item/candidate_push_down → metricflow-0.206.0.dev3/metricflow_semantics/api}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/group_by_item/filter_spec_resolution → metricflow-0.206.0.dev3/metricflow_semantics/api/v0_1}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/assert_one_arg.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/group_by_item/resolution_dag → metricflow-0.206.0.dev3/metricflow_semantics/collection_helpers}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/collection_helpers/merger.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/group_by_item/resolution_dag/resolution_nodes → metricflow-0.206.0.dev3/metricflow_semantics/dag}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/issues → metricflow-0.206.0.dev3/metricflow_semantics/errors}/__init__.py +0 -0
- /metricflow-0.206.0.dev2/metricflow/errors/errors.py → /metricflow-0.206.0.dev3/metricflow_semantics/errors/error_classes.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/issues/filter_spec_resolver → metricflow-0.206.0.dev3/metricflow_semantics/filters}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/filters/merge_where.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/issues/group_by_item_resolver → metricflow-0.206.0.dev3/metricflow_semantics/mf_logging}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/mf_logging/formatting.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/mf_logging/runtime.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/issues/parsing → metricflow-0.206.0.dev3/metricflow_semantics/model}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/graph.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/object_to_reference.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/resolver_inputs → metricflow-0.206.0.dev3/metricflow_semantics/model/semantics}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/semantics/element_group.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/semantics/semantic_model_container.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/query/validation_rules → metricflow-0.206.0.dev3/metricflow_semantics/model/transformations}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/model/transformations/dedupe_metric_input_measures.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/specs → metricflow-0.206.0.dev3/metricflow_semantics/naming}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/naming/linkable_spec_name.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/specs/patterns → metricflow-0.206.0.dev3/metricflow_semantics/protocols}/__init__.py +0 -0
- /metricflow-0.206.0.dev2/metricflow/sql/__init__.py → /metricflow-0.206.0.dev3/metricflow_semantics/py.typed +0 -0
- {metricflow-0.206.0.dev2/metricflow/sql/optimizer → metricflow-0.206.0.dev3/metricflow_semantics/query}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/sql/render → metricflow-0.206.0.dev3/metricflow_semantics/query/group_by_item}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/sql_request → metricflow-0.206.0.dev3/metricflow_semantics/query/group_by_item/candidate_push_down}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/telemetry → metricflow-0.206.0.dev3/metricflow_semantics/query/group_by_item/filter_spec_resolution}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/group_by_item/filter_spec_resolution/filter_location.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/telemetry/handlers → metricflow-0.206.0.dev3/metricflow_semantics/query/group_by_item/resolution_dag}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow/time → metricflow-0.206.0.dev3/metricflow_semantics/query/group_by_item/resolution_dag/resolution_nodes}/__init__.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/query/query_exceptions.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/random_id.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/sql/sql_column_type.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/time/time_constants.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/time/time_source.py +0 -0
- {metricflow-0.206.0.dev2/metricflow → metricflow-0.206.0.dev3/metricflow_semantics}/visitor.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: metricflow
|
|
3
|
-
Version: 0.206.0.
|
|
3
|
+
Version: 0.206.0.dev3
|
|
4
4
|
Summary: Translates a simple metric definition into reusable SQL and executes it against the SQL engine of your choice.
|
|
5
|
-
Project-URL: Documentation, https://
|
|
6
|
-
Project-URL: Source Code, https://github.com/
|
|
5
|
+
Project-URL: Documentation, https://docs.getdbt.com/docs/build/about-metricflow
|
|
6
|
+
Project-URL: Source Code, https://github.com/dbt-labs/metricflow
|
|
7
7
|
Author: dbt Labs
|
|
8
8
|
License-Expression: BUSL-1.1
|
|
9
9
|
License-File: LICENSE
|
|
@@ -13,14 +13,14 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
17
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
17
18
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
18
|
-
Requires-Python: <3.
|
|
19
|
+
Requires-Python: <3.13,>=3.8
|
|
19
20
|
Requires-Dist: dbt-semantic-interfaces<0.6.0,>=0.5.1
|
|
20
21
|
Requires-Dist: graphviz<0.21,>=0.18.2
|
|
21
22
|
Requires-Dist: jinja2>=3.1.3
|
|
22
23
|
Requires-Dist: more-itertools<10.2.0,>=8.10.0
|
|
23
|
-
Requires-Dist: pandas<1.6.0,>=1.5.0
|
|
24
24
|
Requires-Dist: pydantic<1.11.0,>=1.10.0
|
|
25
25
|
Requires-Dist: python-dateutil<2.9.0,>=2.8.2
|
|
26
26
|
Requires-Dist: pyyaml<7.0.0,>=6.0
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
import decimal
|
|
5
|
+
from typing import Sequence, Tuple, Type, Union
|
|
6
|
+
|
|
7
|
+
# Types supported by `MetricFlowDataTable`.
|
|
8
|
+
CellValue = Union[float, str, datetime.datetime, bool, None]
|
|
9
|
+
# Types supported as inputs when building a `MetricFlowDataTable`. These inputs will get converted into
|
|
10
|
+
# one of the `CellValue` types.
|
|
11
|
+
InputCellValue = Union[int, float, str, datetime.datetime, bool, None, decimal.Decimal, datetime.date]
|
|
12
|
+
MetricflowNoneType = type(None)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def row_cell_types(row: Sequence[CellValue]) -> Tuple[Type[CellValue], ...]:
|
|
16
|
+
"""Return the cell type / column type for the objects in the row."""
|
|
17
|
+
return tuple(cell_type(cell) for cell in row)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def cell_type(cell_value: CellValue) -> Type[CellValue]:
|
|
21
|
+
"""Return the cell type / column type for the object in the cell."""
|
|
22
|
+
return type(cell_value)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from functools import cached_property
|
|
5
|
+
from typing import Iterator, Sequence, Tuple, Type
|
|
6
|
+
|
|
7
|
+
from metricflow.data_table.column_types import CellValue
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class ColumnDescription:
|
|
12
|
+
"""Describes a single column in a data table."""
|
|
13
|
+
|
|
14
|
+
column_name: str
|
|
15
|
+
column_type: Type[CellValue]
|
|
16
|
+
|
|
17
|
+
def with_lower_case_column_name(self) -> ColumnDescription: # noqa: D102
|
|
18
|
+
return ColumnDescription(
|
|
19
|
+
column_name=self.column_name.lower(),
|
|
20
|
+
column_type=self.column_type,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class ColumnDescriptionSet:
|
|
26
|
+
"""Describes a collection of columns in a data table."""
|
|
27
|
+
|
|
28
|
+
column_descriptions: Tuple[ColumnDescription, ...]
|
|
29
|
+
|
|
30
|
+
def __iter__(self) -> Iterator[ColumnDescription]: # noqa: D105
|
|
31
|
+
return iter(self.column_descriptions)
|
|
32
|
+
|
|
33
|
+
@cached_property
|
|
34
|
+
def column_names(self) -> Sequence[str]: # noqa: D102
|
|
35
|
+
return tuple(column_description.column_name for column_description in self.column_descriptions)
|
|
36
|
+
|
|
37
|
+
@cached_property
|
|
38
|
+
def column_types(self) -> Sequence[Type]: # noqa: D102
|
|
39
|
+
return tuple(column_description.column_type for column_description in self.column_descriptions)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
import itertools
|
|
5
|
+
import logging
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from decimal import Decimal
|
|
8
|
+
from typing import Iterable, Iterator, List, Optional, Sequence, Tuple, Type
|
|
9
|
+
|
|
10
|
+
import tabulate
|
|
11
|
+
from metricflow_semantics.mf_logging.formatting import indent
|
|
12
|
+
from metricflow_semantics.mf_logging.pretty_print import mf_pformat, mf_pformat_many
|
|
13
|
+
from typing_extensions import Self
|
|
14
|
+
|
|
15
|
+
from metricflow.data_table.column_types import CellValue, InputCellValue, row_cell_types
|
|
16
|
+
from metricflow.data_table.mf_column import ColumnDescription
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True, eq=False)
|
|
22
|
+
class MetricFlowDataTable:
|
|
23
|
+
"""Container for tabular data stored in memory.
|
|
24
|
+
|
|
25
|
+
This is feature-limited and is used to pass tabular data for tests and the CLI. The only data types that are
|
|
26
|
+
supported are described by `CellValue`.
|
|
27
|
+
|
|
28
|
+
When constructing the table, additional input types (as described by `InputCellValue`) can be used, but those
|
|
29
|
+
additional types will be converted into one of the `CellValue` types.
|
|
30
|
+
|
|
31
|
+
Don't use `=` to compare tables as there many be NaNs. Instead, use `check_data_tables_are_equal`.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
column_descriptions: Tuple[ColumnDescription, ...]
|
|
35
|
+
rows: Tuple[Tuple[CellValue, ...], ...]
|
|
36
|
+
|
|
37
|
+
def __post_init__(self) -> None: # noqa: D105
|
|
38
|
+
expected_column_count = self.column_count
|
|
39
|
+
for row_index, row in enumerate(self.rows):
|
|
40
|
+
# Check that the number of columns in the rows match.
|
|
41
|
+
row_column_count = len(row)
|
|
42
|
+
assert row_column_count == expected_column_count, (
|
|
43
|
+
f"Row at index {row_index} has {row_column_count} columns instead of {expected_column_count}. "
|
|
44
|
+
f"Row is:"
|
|
45
|
+
f"\n{indent(mf_pformat(row))}"
|
|
46
|
+
)
|
|
47
|
+
# Check that the type of the object in the rows match.
|
|
48
|
+
for column_index, cell_value in enumerate(row):
|
|
49
|
+
expected_cell_value_type = self.column_descriptions[column_index].column_type
|
|
50
|
+
assert cell_value is None or isinstance(cell_value, expected_cell_value_type), mf_pformat_many(
|
|
51
|
+
"Cell value type mismatch.",
|
|
52
|
+
{
|
|
53
|
+
"row_index": row_index,
|
|
54
|
+
"column_index": column_index,
|
|
55
|
+
"expected_cell_value_type": expected_cell_value_type,
|
|
56
|
+
"actual_cell_value_type": type(cell_value),
|
|
57
|
+
"cell_value": cell_value,
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
# Check that datetimes don't have a timezone set.
|
|
61
|
+
if isinstance(cell_value, datetime.datetime):
|
|
62
|
+
assert cell_value.tzinfo is None, mf_pformat_many(
|
|
63
|
+
"Time zone provided for datetime.",
|
|
64
|
+
{
|
|
65
|
+
"row_index": row_index,
|
|
66
|
+
"column_index": column_index,
|
|
67
|
+
"cell_value": cell_value,
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def column_count(self) -> int: # noqa: D102
|
|
73
|
+
return len(self.column_descriptions)
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def row_count(self) -> int: # noqa: D102
|
|
77
|
+
return len(self.rows)
|
|
78
|
+
|
|
79
|
+
def column_name_index(self, column_name: str) -> int:
|
|
80
|
+
"""Return the index of the column that matches the given name. Raises `ValueError` if the name is invalid."""
|
|
81
|
+
for i, column_description in enumerate(self.column_descriptions):
|
|
82
|
+
if column_description.column_name == column_name:
|
|
83
|
+
return i
|
|
84
|
+
raise ValueError(
|
|
85
|
+
f"Unknown column name {repr(column_name)}. Known column names are:"
|
|
86
|
+
f"\n{indent(mf_pformat([column_name for column_name in self.column_descriptions]))}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def column_names(self) -> Sequence[str]: # noqa: D102
|
|
91
|
+
return tuple(column_description.column_name for column_description in self.column_descriptions)
|
|
92
|
+
|
|
93
|
+
def column_values_iterator(self, column_index: int) -> Iterator[CellValue]:
|
|
94
|
+
"""Returns an iterator for values of the column at the tiven index."""
|
|
95
|
+
return (row[column_index] for row in self.rows)
|
|
96
|
+
|
|
97
|
+
def _sorted_by_column_name(self) -> MetricFlowDataTable: # noqa: D102
|
|
98
|
+
new_rows: List[List[CellValue]] = [[] for _ in range(self.row_count)]
|
|
99
|
+
sorted_column_names = sorted(self.column_names)
|
|
100
|
+
for column_name in sorted_column_names:
|
|
101
|
+
old_column_index = self.column_name_index(column_name)
|
|
102
|
+
for row_index, cell_value in enumerate(self.column_values_iterator(old_column_index)):
|
|
103
|
+
new_rows[row_index].append(cell_value)
|
|
104
|
+
|
|
105
|
+
return MetricFlowDataTable(
|
|
106
|
+
column_descriptions=tuple(
|
|
107
|
+
self.column_descriptions[self.column_name_index(column_name)] for column_name in sorted_column_names
|
|
108
|
+
),
|
|
109
|
+
rows=tuple(
|
|
110
|
+
tuple(row_dict[column_index] for column_index in range(self.column_count)) for row_dict in new_rows
|
|
111
|
+
),
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def _sorted_by_row(self) -> MetricFlowDataTable: # noqa: D102
|
|
115
|
+
def _cell_sort_key(cell: CellValue) -> str:
|
|
116
|
+
if isinstance(cell, datetime.datetime):
|
|
117
|
+
return cell.isoformat()
|
|
118
|
+
return str(cell)
|
|
119
|
+
|
|
120
|
+
def _row_sort_key(row: Tuple[CellValue, ...]) -> Tuple[str, ...]:
|
|
121
|
+
return tuple(_cell_sort_key(cell) for cell in row)
|
|
122
|
+
|
|
123
|
+
return MetricFlowDataTable(
|
|
124
|
+
column_descriptions=self.column_descriptions,
|
|
125
|
+
rows=tuple(sorted((row for row in self.rows), key=_row_sort_key)),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def sorted(self) -> MetricFlowDataTable:
|
|
129
|
+
"""Returns this but with the columns in order by name, and the rows in order by values."""
|
|
130
|
+
return self._sorted_by_column_name()._sorted_by_row()
|
|
131
|
+
|
|
132
|
+
def text_format(self, float_decimals: int = 2) -> str:
|
|
133
|
+
"""Return a text version of this table that is suitable for printing."""
|
|
134
|
+
str_rows: List[List[str]] = []
|
|
135
|
+
for row in self.rows:
|
|
136
|
+
str_row: List[str] = []
|
|
137
|
+
for cell_value in row:
|
|
138
|
+
if isinstance(cell_value, float):
|
|
139
|
+
str_row.append(f"{cell_value:.{float_decimals}f}")
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
if isinstance(cell_value, datetime.datetime):
|
|
143
|
+
str_row.append(cell_value.isoformat())
|
|
144
|
+
continue
|
|
145
|
+
|
|
146
|
+
str_row.append(str(cell_value))
|
|
147
|
+
str_rows.append(str_row)
|
|
148
|
+
return tabulate.tabulate(
|
|
149
|
+
tabular_data=tuple(tuple(str_row) for str_row in str_rows),
|
|
150
|
+
headers=tuple(column_description.column_name for column_description in self.column_descriptions),
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def with_lower_case_column_names(self) -> MetricFlowDataTable:
|
|
154
|
+
"""Return this but with columns names in lowercase."""
|
|
155
|
+
return MetricFlowDataTable(
|
|
156
|
+
column_descriptions=tuple(
|
|
157
|
+
column_description.with_lower_case_column_name() for column_description in self.column_descriptions
|
|
158
|
+
),
|
|
159
|
+
rows=self.rows,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
def get_cell_value(self, row_index: int, column_index: int) -> CellValue: # noqa: D102
|
|
163
|
+
return self.rows[row_index][column_index]
|
|
164
|
+
|
|
165
|
+
@staticmethod
|
|
166
|
+
def create_from_rows( # noqa: D102
|
|
167
|
+
column_names: Sequence[str], rows: Iterable[Sequence[InputCellValue]]
|
|
168
|
+
) -> MetricFlowDataTable:
|
|
169
|
+
builder = _MetricFlowDataTableBuilder(column_names)
|
|
170
|
+
for row in rows:
|
|
171
|
+
builder.add_row(row)
|
|
172
|
+
return builder.build()
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class _MetricFlowDataTableBuilder:
|
|
176
|
+
"""Helps build `MetricFlowDataTable`, one row at a time.
|
|
177
|
+
|
|
178
|
+
This validates each row as it is input to give better error messages.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
def __init__(self, column_names: Sequence[str]) -> None: # noqa: D107
|
|
182
|
+
self._rows: List[Tuple[CellValue, ...]] = []
|
|
183
|
+
self._column_names = tuple(column_names)
|
|
184
|
+
|
|
185
|
+
def _build_table_from_rows(self) -> MetricFlowDataTable: # noqa: D102
|
|
186
|
+
# Figure out the type of the column based on the types of the values in the rows.
|
|
187
|
+
# Can't use the type of the columns in the first row because it might contain None, so iterate through the rows
|
|
188
|
+
# and use the first non-None type.
|
|
189
|
+
column_types_so_far: Optional[Tuple[Type[CellValue], ...]] = None
|
|
190
|
+
cell_value: CellValue
|
|
191
|
+
for row in self._rows:
|
|
192
|
+
if column_types_so_far is None:
|
|
193
|
+
column_types_so_far = row_cell_types(row)
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
# If the types of the objects in the row are the same, no need for updates.
|
|
197
|
+
row_column_types = row_cell_types(row)
|
|
198
|
+
if row_column_types == column_types_so_far:
|
|
199
|
+
continue
|
|
200
|
+
|
|
201
|
+
# Types of objects in the row are different from what's known so far.
|
|
202
|
+
# They can only be different in that one can be None and other can be not None.
|
|
203
|
+
updated_column_types: List[Type[CellValue]] = []
|
|
204
|
+
for column_type_so_far, cell_type, cell_value in itertools.zip_longest(
|
|
205
|
+
column_types_so_far, row_column_types, row
|
|
206
|
+
):
|
|
207
|
+
if column_type_so_far is cell_type:
|
|
208
|
+
updated_column_types.append(column_type_so_far)
|
|
209
|
+
elif column_type_so_far is type(None) and cell_type is not None:
|
|
210
|
+
updated_column_types.append(cell_type)
|
|
211
|
+
elif column_type_so_far is not None and cell_type is type(None):
|
|
212
|
+
updated_column_types.append(column_type_so_far)
|
|
213
|
+
else:
|
|
214
|
+
raise ValueError(f"Expected cell type {column_type_so_far} but got: {cell_type}")
|
|
215
|
+
|
|
216
|
+
column_types_so_far = tuple(updated_column_types)
|
|
217
|
+
|
|
218
|
+
# Empty table case.
|
|
219
|
+
if column_types_so_far is None:
|
|
220
|
+
column_types_so_far = tuple(type(None) for _ in range(len(self._column_names)))
|
|
221
|
+
|
|
222
|
+
final_column_types = column_types_so_far
|
|
223
|
+
|
|
224
|
+
return MetricFlowDataTable(
|
|
225
|
+
column_descriptions=tuple(
|
|
226
|
+
ColumnDescription(column_name=column_name, column_type=column_type)
|
|
227
|
+
for column_name, column_type in itertools.zip_longest(self._column_names, final_column_types)
|
|
228
|
+
),
|
|
229
|
+
rows=tuple(self._rows),
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
def _convert_row_to_supported_types(self, row: Sequence[InputCellValue]) -> Sequence[CellValue]:
|
|
233
|
+
"""Since only a limited set of types are supported, convert the input type to the supported type."""
|
|
234
|
+
updated_row: List[CellValue] = []
|
|
235
|
+
for cell_value in row:
|
|
236
|
+
if (
|
|
237
|
+
cell_value is None
|
|
238
|
+
or isinstance(cell_value, float)
|
|
239
|
+
or isinstance(cell_value, bool)
|
|
240
|
+
or isinstance(cell_value, int)
|
|
241
|
+
or isinstance(cell_value, str)
|
|
242
|
+
):
|
|
243
|
+
updated_row.append(cell_value)
|
|
244
|
+
continue
|
|
245
|
+
|
|
246
|
+
if isinstance(cell_value, datetime.datetime):
|
|
247
|
+
updated_row.append(cell_value.replace(tzinfo=None))
|
|
248
|
+
continue
|
|
249
|
+
|
|
250
|
+
if isinstance(cell_value, Decimal):
|
|
251
|
+
updated_row.append(float(cell_value))
|
|
252
|
+
continue
|
|
253
|
+
|
|
254
|
+
if isinstance(cell_value, datetime.date):
|
|
255
|
+
updated_row.append(datetime.datetime.combine(cell_value, datetime.datetime.min.time()))
|
|
256
|
+
continue
|
|
257
|
+
|
|
258
|
+
raise ValueError(f"Row cell has unexpected type: {repr(cell_value)}")
|
|
259
|
+
return updated_row
|
|
260
|
+
|
|
261
|
+
def add_row(self, row: Sequence[InputCellValue], parse_strings: bool = False) -> Self: # noqa: D102
|
|
262
|
+
row = tuple(row)
|
|
263
|
+
expected_column_count = len(self._column_names)
|
|
264
|
+
actual_column_count = len(row)
|
|
265
|
+
if actual_column_count != expected_column_count:
|
|
266
|
+
raise ValueError(
|
|
267
|
+
f"Input row has {actual_column_count} columns, but expected {expected_column_count} columns. Row is:"
|
|
268
|
+
f"\n{indent(mf_pformat(row))}"
|
|
269
|
+
)
|
|
270
|
+
self._rows.append(tuple(self._convert_row_to_supported_types(row)))
|
|
271
|
+
return self
|
|
272
|
+
|
|
273
|
+
def build(self) -> MetricFlowDataTable: # noqa: D102
|
|
274
|
+
return self._build_table_from_rows()
|