# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: v1/api.public.proto
# plugin: python-betterproto
import builtins
from dataclasses import dataclass
from datetime import datetime
from typing import (
    TYPE_CHECKING,
    Dict,
    List,
    Optional,
)

import betterproto
import betterproto.lib.google.protobuf as betterproto_lib_google_protobuf
import grpclib
from betterproto.grpc.grpclib_server import ServiceBase


if TYPE_CHECKING:
    import grpclib.server
    from betterproto.grpc.grpclib_client import MetadataLike
    from grpclib.metadata import Deadline


class AnalysisType(betterproto.Enum):
    """Type of Analysis eg. KEY_DRIVER."""

    ANALYSIS_TYPE_UNKNOWN = 0
    ANALYSIS_TYPE_GENERAL_PERFORMANCE = 1
    ANALYSIS_TYPE_TREND = 2
    ANALYSIS_TYPE_TIME_COMPARE = 3
    ANALYSIS_TYPE_GROUP_COMPARE = 4


class SqlDataType(betterproto.Enum):
    """Represents a datatype of a specific dimension."""

    SQL_DATA_TYPE_UNKNOWN = 0
    SQL_DATA_TYPE_STRING = 1
    SQL_DATA_TYPE_FLOAT = 2
    SQL_DATA_TYPE_TIMESTAMP = 3
    SQL_DATA_TYPE_INT = 4
    SQL_DATA_TYPE_BOOLEAN = 5


class ExpressionBasicExpressionOperator(betterproto.Enum):
    OPERATOR_UNKNOWN = 0
    OPERATOR_LT = 1
    OPERATOR_EQ = 2
    OPERATOR_LTE = 3
    OPERATOR_GTE = 4
    OPERATOR_GT = 5
    OPERATOR_NE = 6
    OPERATOR_LIKE = 7
    OPERATOR_NOT_LIKE = 8
    OPERATOR_IS = 9
    OPERATOR_IS_NOT = 10


class AnalysisResultRunStatus(betterproto.Enum):
    """Status of running an analysis."""

    RUN_STATUS_UNKNOWN = 0
    RUN_STATUS_IN_FLIGHT = 1
    """Analysis is currently running."""

    RUN_STATUS_FAILED = 2
    """Analysis finished running but had errors."""

    RUN_STATUS_COMPLETED = 3
    """Analysis ran successfully."""


class AnalysisResultRunType(betterproto.Enum):
    """Either SCHEDULED or MANUAL."""

    RUN_TYPE_UNKNOWN = 0
    RUN_TYPE_SCHEDULED = 1
    RUN_TYPE_MANUAL = 2


class KeyDriverAnalysisResultSegmentConfidenceLevel(betterproto.Enum):
    """
    Reflects how interesting/valuable Sisu determines a specific segment to be.
    """

    CONFIDENCE_LEVEL_UNKNOWN = 0
    CONFIDENCE_LEVEL_HIGH = 1
    CONFIDENCE_LEVEL_MEDIUM = 2
    CONFIDENCE_LEVEL_LOW = 3


class KeyDriverAnalysisResultSegmentCustomCalculationType(betterproto.Enum):
    """Custom calculation types."""

    CUSTOM_CALCULATION_TYPE_UNKNOWN = 0
    CUSTOM_CALCULATION_TYPE_SUM = 1
    CUSTOM_CALCULATION_TYPE_AVERAGE = 2
    CUSTOM_CALCULATION_TYPE_COUNT = 3
    CUSTOM_CALCULATION_TYPE_CHANGE_IN_SUM = 4
    CUSTOM_CALCULATION_TYPE_CHANGE_IN_AVERAGE = 5
    CUSTOM_CALCULATION_TYPE_CHANGE_IN_COUNT = 6
    CUSTOM_CALCULATION_TYPE_CHANGE_IN_SIZE = 7
    CUSTOM_CALCULATION_TYPE_RATE_EFFECT = 8
    CUSTOM_CALCULATION_TYPE_MIX_SHIFT_EFFECT = 9
    CUSTOM_CALCULATION_TYPE_MIX_SHIFT_EFFECT_B_NORMALIZED = 10
    CUSTOM_CALCULATION_TYPE_NET_EFFECT = 11
    CUSTOM_CALCULATION_TYPE_NET_EFFECT_B_NORMALIZED = 12
    CUSTOM_CALCULATION_TYPE_RELATIVE_CHANGE = 13
    CUSTOM_CALCULATION_TYPE_RELATIVE_PERCENT_CHANGE_OF_METRIC = 14
    CUSTOM_CALCULATION_TYPE_CHANGE_IN_WEIGHTED_CATEGORICAL_GP_IMPACT = 15


class UnitsConfigUnitType(betterproto.Enum):
    UNIT_TYPE_UNKNOWN = 0
    UNIT_TYPE_CUSTOM = 1
    UNIT_TYPE_PERCENT = 2
    UNIT_TYPE_CURRENCY = 3
    UNIT_TYPE_BPS = 4
    UNIT_TYPE_NUMBER = 5


class MetricDesiredDirection(betterproto.Enum):
    """Type of metric direction."""

    DESIRED_DIRECTION_UNKNOWN = 0
    DESIRED_DIRECTION_INCREASE = 1
    DESIRED_DIRECTION_DECREASE = 2


class MetricMetricType(betterproto.Enum):
    """
    Type of metric calculation that is used to evaluate the metric's dimension.
    """

    METRIC_TYPE_UNKNOWN = 0
    METRIC_TYPE_AVERAGE = 1
    """Average of a single metric dimension(e.g., average order value)."""

    METRIC_TYPE_SUM = 2
    """Sum of a single metric dimension(e.g., total revenue)."""

    METRIC_TYPE_WEIGHTED_SUM = 3
    """
    Sum of a metric dimension weighted by a weight dimension(e.g., price per
    share).
    """

    METRIC_TYPE_WEIGHTED_AVERAGE = 4
    """
    Average of a metric dimension weighted by a weight dimension(e.g., price
    per share).
    """

    METRIC_TYPE_CATEGORICAL_COUNT = 5
    """
    Count of a matching condition in a metric dimension(e.g., number of
    churns).
    """

    METRIC_TYPE_CATEGORICAL_RATE = 6
    """
    Rate of a matching condition in a metric dimension(e.g., churn rate).
    """

    METRIC_TYPE_COUNT_DISTINCT = 7
    """
    Count of a matching condition in a metric dimension(e.g., number of
    churns).
    """

    METRIC_TYPE_NUMERICAL_COUNT = 8
    """
    Count of the rows of a single metric dimension(e.g., number of orders).
    """

    METRIC_TYPE_NUMERICAL_RATE = 9
    """
    A metric dimension divided by a denominator dimension(e.g., lead conversion
    rate).
    """


class DataSourceDataSourceType(betterproto.Enum):
    DATA_SOURCE_TYPE_UNKNOWN = 0
    DATA_SOURCE_TYPE_REDSHIFT = 1
    DATA_SOURCE_TYPE_POSTGRESQL = 2
    DATA_SOURCE_TYPE_SNOWFLAKE = 3
    DATA_SOURCE_TYPE_SQLSERVER = 4
    DATA_SOURCE_TYPE_BIGQUERY = 5
    DATA_SOURCE_TYPE_VERTICA = 6
    DATA_SOURCE_TYPE_AWSATHENA = 7
    DATA_SOURCE_TYPE_SPARK = 8
    DATA_SOURCE_TYPE_DATABRICKS = 9
    DATA_SOURCE_TYPE_SAP = 10
    DATA_SOURCE_TYPE_CSV = 11
    DATA_SOURCE_TYPE_DBTCLOUD = 12


class DatasetDatasetType(betterproto.Enum):
    DATASET_TYPE_UNKNOWN = 0
    DATASET_TYPE_TABLE = 1
    """Data is sourced from a single table."""

    DATASET_TYPE_QUERY = 2
    """Data is sourced from a user-defined query."""


@dataclass(eq=False, repr=False)
class GetAnalysisFiltersRequest(betterproto.Message):
    """Request parameters for analysis filters endpoints"""

    id: Optional[int] = betterproto.message_field(1, wraps=betterproto.TYPE_INT64)
    """Analysis id."""


@dataclass(eq=False, repr=False)
class SetAnalysisFiltersRequest(betterproto.Message):
    """Request parameters for analysis filters endpoints"""

    id: Optional[int] = betterproto.message_field(1, wraps=betterproto.TYPE_INT64)
    """Analysis id."""

    filter_expression: "Expression" = betterproto.message_field(2)
    """
    A filter expression must be one of 'and'/'or' [expression] with min of 2
    expressions. or a single basicCondition.
    """


@dataclass(eq=False, repr=False)
class SetAnalysisFiltersResponse(betterproto.Message):
    """Response with empty message."""

    pass


@dataclass(eq=False, repr=False)
class GetAnalysisFiltersResponse(betterproto.Message):
    """Response for analysis filter endpoint."""

    filter_expression: "Expression" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class Expression(betterproto.Message):
    """An Expression which would facilitate building a filter expression."""

    and_: "ExpressionAndExpression" = betterproto.message_field(
        1, group="expression_value"
    )
    or_: "ExpressionOrExpression" = betterproto.message_field(
        2, group="expression_value"
    )
    basic_condition: "ExpressionBasicExpression" = betterproto.message_field(
        3, group="expression_value"
    )


@dataclass(eq=False, repr=False)
class ExpressionAndExpression(betterproto.Message):
    """A conjunction of boolean expressions  e.g. `<expr1> AND <expr2>`."""

    expressions: List["Expression"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class ExpressionOrExpression(betterproto.Message):
    """
    A conjunction of boolean expressions  e.g. `<expr1> OR <expr2>`. An OR
    expression must no have AND expression.
    """

    expressions: List["Expression"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class ExpressionLiteral(betterproto.Message):
    """literal represent the data type and value of a dimension."""

    bool: builtins.bool = betterproto.bool_field(1, group="value")
    int: builtins.int = betterproto.int64_field(2, group="value")
    string: str = betterproto.string_field(3, group="value")
    float: builtins.float = betterproto.double_field(4, group="value")
    timestamp: datetime = betterproto.message_field(5, group="value")


@dataclass(eq=False, repr=False)
class ExpressionBasicExpression(betterproto.Message):
    """
    An basic boolean expression e.g. `"sale_price" > 100`. {   "dimensionName"
    : "sale_price",   "operator" : "OPERATOR_LT",   "literal" : {     "int" :
    100   } }
    """

    operator: "ExpressionBasicExpressionOperator" = betterproto.enum_field(1)
    dimension_name: str = betterproto.string_field(2)
    """A SQL identifier name, e.g 'my_column'"""

    null_literal: "betterproto_lib_google_protobuf.Empty" = betterproto.message_field(
        3, group="literal_value"
    )
    literal: "ExpressionLiteral" = betterproto.message_field(4, group="literal_value")


@dataclass(eq=False, repr=False)
class AnalysisRunResultsRequest(betterproto.Message):
    """Request parameters for get analysis results."""

    limit: Optional[int] = betterproto.message_field(1, wraps=betterproto.TYPE_UINT64)
    """
    A limit on the number of objects to be returned, between 1 and 10000.
    Default value is 10000.
    """

    starting_after: Optional[int] = betterproto.message_field(
        2, wraps=betterproto.TYPE_INT64
    )
    """
    starting_after is an object ID that defines your place in the list. For
    instance, if you make a analysis list request and receive 100, ending with
    id = 89, your subsequent call can include starting_after=89 in order to
    fetch the next page of the list.
    """

    confidence_gte: Optional[str] = betterproto.message_field(
        3, wraps=betterproto.TYPE_STRING
    )
    """
    filter by confidence levels of greater than equal to HIGH, MEDIUM or LOW
    """

    id: Optional[int] = betterproto.message_field(4, wraps=betterproto.TYPE_INT64)
    """Analysis Id."""


@dataclass(eq=False, repr=False)
class AnalysesListRequest(betterproto.Message):
    """Request parameters for get analysis list."""

    analysis_type: "AnalysisType" = betterproto.enum_field(1)
    """
    What type of analyses to include in the results. If not set all types will
    be returned.
    """

    limit: Optional[int] = betterproto.message_field(2, wraps=betterproto.TYPE_UINT64)
    """
    A limit on the number of objects to be returned, between 1 and 10000.
    Default value is 10000.
    """

    starting_after: Optional[int] = betterproto.message_field(
        3, wraps=betterproto.TYPE_INT64
    )
    """
    starting_after is an object ID that defines your place in the list. For
    instance, if you make a analysis list request and receive 100, ending with
    id = 89, your subsequent call can include starting_after=89 in order to
    fetch the next page of the list.
    """


@dataclass(eq=False, repr=False)
class AnalysesListResponse(betterproto.Message):
    """AnalysesListResponse provides list of Analyses."""

    analyses: List["Analysis"] = betterproto.message_field(1)
    """List of analyses."""

    pagination_hints: "PaginationHints" = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class Analysis(betterproto.Message):
    """Provides detailed information about an analysis."""

    id: int = betterproto.int64_field(1)
    """Analysis id."""

    name: str = betterproto.string_field(2)
    """Analysis name."""

    type: "AnalysisType" = betterproto.enum_field(3)
    """Type of Analysis eg. TYPE_KEY_DRIVER."""

    created_at: datetime = betterproto.message_field(4)
    """Timestamp when the analysis was created."""

    metric_id: int = betterproto.uint64_field(5)
    """Metric id corresponding to the analysis."""

    project_id: int = betterproto.uint64_field(6)
    """Project id corresponding to the analysis."""

    application_url: str = betterproto.string_field(7)
    """
    Link to the live sisu analysis this represents. ex:
    vip.sisudata.com/projects/{id}/analysis/{id}
    """


@dataclass(eq=False, repr=False)
class RunAnalysisRequest(betterproto.Message):
    """Request payload for execute analysis workflow."""

    id: int = betterproto.int64_field(1)
    """Analysis id."""


@dataclass(eq=False, repr=False)
class RunAnalysisResponse(betterproto.Message):
    """Response message execute analysis workflow returns empty message"""

    pass


@dataclass(eq=False, repr=False)
class PaginationHints(betterproto.Message):
    """
    Pagination hints which indicate if more data is available
    next_starting_cursor indicate the next id to be used for starting_after
    pagination parameter
    """

    has_more: bool = betterproto.bool_field(1)
    next_starting_cursor: Optional[int] = betterproto.message_field(
        2, wraps=betterproto.TYPE_INT64
    )


@dataclass(eq=False, repr=False)
class AnalysisRunResultsResponse(betterproto.Message):
    """Response payload for get LatestAnalysisResult."""

    analysis_result: "AnalysisResult" = betterproto.message_field(1)
    """Analysis Result."""

    pagination_hints: "PaginationHints" = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class KdaSummaryCard(betterproto.Message):
    """Information specific to a single card in a summary."""

    card_label: str = betterproto.string_field(1)
    """Summary card label (bolded in UI)."""

    category_filter: Optional[str] = betterproto.message_field(
        2, wraps=betterproto.TYPE_STRING
    )
    """
    String representation of the filter that produces the metric category.
    """

    summary_value: Optional[float] = betterproto.double_field(
        4, optional=True, group="_summary_value"
    )
    """Value of the metric for the specified subgroup."""

    match_size: Optional[float] = betterproto.double_field(
        5, optional=True, group="_match_size"
    )
    """
    Number of rows matching the filter expression in the specified subgroup.
    """

    total_size: Optional[float] = betterproto.double_field(
        6, optional=True, group="_total_size"
    )
    """Number of total rows in the specified subgroup."""

    min: Optional[float] = betterproto.double_field(7, optional=True, group="_min")
    """Minimum of metric dimension column in the specified subgroup."""

    max: Optional[float] = betterproto.double_field(8, optional=True, group="_max")
    """Maximum of metric dimension column in the specified subgroup."""

    median: Optional[float] = betterproto.double_field(
        9, optional=True, group="_median"
    )
    """Median of metric dimension column in the specified subgroup."""

    average: Optional[float] = betterproto.double_field(
        10, optional=True, group="_average"
    )
    """Average of metric dimension column in the specified subgroup."""

    weighted_average: Optional[float] = betterproto.double_field(
        11, optional=True, group="_weighted_average"
    )
    """
    Weighted average of metric dimension column against specified weight column
    in the specified subgroup.
    """

    sum: Optional[float] = betterproto.double_field(12, optional=True, group="_sum")
    """Sum of metric dimension column in the specified subgroup."""

    weighted_sum: Optional[float] = betterproto.double_field(
        13, optional=True, group="_weighted_sum"
    )
    """
    Weighted sum of metric dimension column against specified weight column in
    the specified subgroup.
    """

    weight: Optional[float] = betterproto.double_field(
        14, optional=True, group="_weight"
    )
    """Sum of weight dimension column in the specified subgroup."""

    total_numerator: Optional[float] = betterproto.double_field(
        15, optional=True, group="_total_numerator"
    )
    """Sum of numerator dimension column in the specified subgroup."""

    total_denominator: Optional[float] = betterproto.double_field(
        16, optional=True, group="_total_denominator"
    )
    """Sum of denominator dimension column in the specified subgroup."""


@dataclass(eq=False, repr=False)
class GroupComparisonSummaryCard(betterproto.Message):
    """Summary card details specific to a group comparison."""

    group_a_card: "KdaSummaryCard" = betterproto.message_field(1)
    """Summary card for group A."""

    group_b_card: "KdaSummaryCard" = betterproto.message_field(2)
    """Summary card for group B."""

    group_a_filter: str = betterproto.string_field(3)
    """Filter that produces group A."""

    group_b_filter: str = betterproto.string_field(4)
    """Filter that produces group B."""

    percent_change: float = betterproto.double_field(5)
    """Percent change of metric value from group A to group B."""


@dataclass(eq=False, repr=False)
class TimeComparisonSummaryCard(betterproto.Message):
    """Summary card details specific to a time comparison."""

    current_period_card: "KdaSummaryCard" = betterproto.message_field(1)
    """Summary card for current period."""

    previous_period_card: "KdaSummaryCard" = betterproto.message_field(2)
    """Summary card for previous period."""

    current_period: "TimeRange" = betterproto.message_field(3)
    """Current period start (inclusive) and end (exclusive) datetimes."""

    previous_period: "TimeRange" = betterproto.message_field(4)
    """Previous period start (inclusive) and end (exclusive) datetimes."""

    percent_change: float = betterproto.double_field(5)
    """
    Percent change of metric value from previous period to current period.
    """


@dataclass(eq=False, repr=False)
class TrendSummaryCard(betterproto.Message):
    """Summary card details of an individual overall trend."""

    card_label: str = betterproto.string_field(1)
    """Summary card label (bolded in UI)."""

    slope: float = betterproto.double_field(2)
    """Slope of the metric over the trend period."""

    percent_change: float = betterproto.double_field(11)
    """
    Percent increase or decrease of metric dimension column in the first time
    unit of a trend.
    """

    denominator_label: str = betterproto.string_field(12)
    """Analysis summary period; visible for trend detection analyses."""


@dataclass(eq=False, repr=False)
class TrendSummaryCardInfo(betterproto.Message):
    """Summary card details specific to a trend detection."""

    current_period: "TrendSummaryCard" = betterproto.message_field(1)
    """Most-recent overall trend summary card."""

    previous_period: "TrendSummaryCard" = betterproto.message_field(2)
    """Second-most-recent overall trend summary card."""


@dataclass(eq=False, repr=False)
class KdaSummaryCardInfo(betterproto.Message):
    """Summary card details of a KDA result."""

    metric_type_label: str = betterproto.string_field(1)
    """Metric label present for KDAs; example: "Numerical Count"""

    general_performance_card: "KdaSummaryCard" = betterproto.message_field(
        2, group="card_type"
    )
    """General performance KDA summary card."""

    group_comparison_card: "GroupComparisonSummaryCard" = betterproto.message_field(
        3, group="card_type"
    )
    """Group comparison KDA summary card."""

    time_comparison_card: "TimeComparisonSummaryCard" = betterproto.message_field(
        4, group="card_type"
    )
    """Time comparison KDA summary card."""


@dataclass(eq=False, repr=False)
class AnalysisResult(betterproto.Message):
    """Provides details of an analysis run."""

    id: int = betterproto.int64_field(1)
    """
    The run ID Analysis run. Run ID's are unique across analyses. example:
    102940
    """

    run_status: "AnalysisResultRunStatus" = betterproto.enum_field(2)
    """Indicates if analysis run completed successfully or not."""

    requested_at: datetime = betterproto.message_field(3)
    """Time at which run was kicked off."""

    completed_at: datetime = betterproto.message_field(4)
    """Time at which analysis run completed."""

    run_type: "AnalysisResultRunType" = betterproto.enum_field(5)
    key_driver_analysis_result: "KeyDriverAnalysisResult" = betterproto.message_field(
        6, group="run_result"
    )
    trend_analysis_result: "TrendAnalysisResult" = betterproto.message_field(
        7, group="run_result"
    )
    metric_id: int = betterproto.uint64_field(8)
    """Metric ID for the analysis."""

    application_url: str = betterproto.string_field(9)
    """
    Link to the live sisu analysis this represents. ex:
    vip.sisudata.com/projects/{id}/analysis/{id}
    """

    result_version: Optional[str] = betterproto.string_field(
        10, optional=True, group="_result_version"
    )
    """
    result_version id is used to identify new incremental results while
    analysis is still in flight.
    """


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResult(betterproto.Message):
    """Provides details of a key driver analysis run."""

    summary_card: "KdaSummaryCardInfo" = betterproto.message_field(1)
    """Summary information for the key driver analysis."""

    time_comparison: "KeyDriverAnalysisResultTimeComparison" = (
        betterproto.message_field(6, group="comparison")
    )
    """
    If subtype is TIME_COMPARISON, metadata about the time periods that are
    compared.
    """

    group_comparison: "KeyDriverAnalysisResultGroupComparison" = (
        betterproto.message_field(7, group="comparison")
    )
    """
    If subtype is GROUP_COMPARISON metadata about the groups that are being
    compared.
    """

    general_performance: "KeyDriverAnalysisResultGeneralPerformance" = (
        betterproto.message_field(8, group="comparison")
    )
    """If the subtype is General_Performance."""

    segments: List["KeyDriverAnalysisResultSegment"] = betterproto.message_field(10)
    """Array of the segments selected by the key driver algorithm."""


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultTimeComparison(betterproto.Message):
    """
    If subtype is TIME_COMPARISON, metadata about the time periods that are
    compared.
    """

    previous_period: "TimeRange" = betterproto.message_field(1)
    """The earlier of the two periods being compared."""

    recent_period: "TimeRange" = betterproto.message_field(2)
    """The more recent of the two periods being compared."""


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultGroupComparison(betterproto.Message):
    """
    If subtype is GROUP_COMPARISON metadata about the groups that are being
    compared.
    """

    group_a: "KeyDriverAnalysisResultGroupComparisonGroupDescription" = (
        betterproto.message_field(1)
    )
    """The first group."""

    group_b: "KeyDriverAnalysisResultGroupComparisonGroupDescription" = (
        betterproto.message_field(2)
    )
    """The second group."""


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultGroupComparisonGroupDescription(betterproto.Message):
    name: str = betterproto.string_field(1)
    """The user-defined name corresponding to the first group."""


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultGeneralPerformance(betterproto.Message):
    """If subtype is General Performance."""

    pass


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultSegment(betterproto.Message):
    """Segment of a key driver analysis run."""

    id: int = betterproto.int64_field(1)
    """Unique ID corresponding to each segment, unique per analysis run."""

    factors: Dict[str, "Factor"] = betterproto.map_field(
        3, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    """
    The factors that define this segment, represented as a map of Dimension to
    Value.
    """

    group_comparison: "KeyDriverAnalysisResultSegmentGroupComparisonPerformance" = (
        betterproto.message_field(4, group="details")
    )
    time_comparison: "KeyDriverAnalysisResultSegmentTimeComparisonPerformance" = (
        betterproto.message_field(5, group="details")
    )
    general_performance: "KeyDriverAnalysisResultSegmentGeneralPerformance" = (
        betterproto.message_field(6, group="details")
    )
    impact: Optional[float] = betterproto.message_field(
        7, wraps=betterproto.TYPE_DOUBLE
    )
    """
    How much this segment contributes to the overall value of the metric
    calculation.
    """

    confidence: "KeyDriverAnalysisResultSegmentConfidenceLevel" = (
        betterproto.enum_field(8)
    )
    """
    Interpretation of q-value as the confidence of the impact on the metric.
    """

    custom_calculations: List[
        "KeyDriverAnalysisResultSegmentCustomCalculation"
    ] = betterproto.message_field(9)
    """custom calculation statistics."""


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultSegmentGroupComparisonPerformance(betterproto.Message):
    """
    If analysis type is GROUP_COMPARISON the metric value and size of the
    compared segments.
    """

    group_a_size: Optional[float] = betterproto.message_field(
        1, wraps=betterproto.TYPE_DOUBLE
    )
    """The size of this segment in the first group."""

    group_b_size: Optional[float] = betterproto.message_field(
        2, wraps=betterproto.TYPE_DOUBLE
    )
    """The size of this segment in the second group."""

    group_a_value: Optional[float] = betterproto.message_field(
        3, wraps=betterproto.TYPE_DOUBLE
    )
    """The value of the metric for this segment in the first group."""

    group_b_value: Optional[float] = betterproto.message_field(
        4, wraps=betterproto.TYPE_DOUBLE
    )
    """The value of the metric for this segment in the second group."""


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultSegmentTimeComparisonPerformance(betterproto.Message):
    """
    If analysis type is TIME_COMPARISON,  the metric value and size of the
    compared segments.
    """

    previous_period_size: Optional[float] = betterproto.message_field(
        1, wraps=betterproto.TYPE_DOUBLE
    )
    """The size of this segment in the earlier of the compared periods."""

    recent_period_size: Optional[float] = betterproto.message_field(
        2, wraps=betterproto.TYPE_DOUBLE
    )
    """The size of this segment in the more recent of the compared periods."""

    previous_period_value: Optional[float] = betterproto.message_field(
        3, wraps=betterproto.TYPE_DOUBLE
    )
    """
    The value of the metric for this segment in the earlier of the compared
    periods.
    """

    recent_period_value: Optional[float] = betterproto.message_field(
        4, wraps=betterproto.TYPE_DOUBLE
    )
    """
    The value of the metric for this segment in the more recent of the compared
    periods.
    """


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultSegmentGeneralPerformance(betterproto.Message):
    """
    If analysis type is GENERAL_PERFORMANCE the metric value and size for this
    segment.
    """

    size: Optional[float] = betterproto.message_field(1, wraps=betterproto.TYPE_DOUBLE)
    """
    The size (in percent) of this segment relative to the overall population.
    """

    value: Optional[float] = betterproto.message_field(2, wraps=betterproto.TYPE_DOUBLE)
    """The metric value corresponding to this segment."""


@dataclass(eq=False, repr=False)
class KeyDriverAnalysisResultSegmentCustomCalculation(betterproto.Message):
    calculation_type: "KeyDriverAnalysisResultSegmentCustomCalculationType" = (
        betterproto.enum_field(1)
    )
    """The calculation type of the statistic."""

    name: str = betterproto.string_field(2)
    """The readable name of the statistic."""

    value: Optional[float] = betterproto.message_field(3, wraps=betterproto.TYPE_DOUBLE)
    """The value of the custom calculation statistic."""


@dataclass(eq=False, repr=False)
class TrendAnalysisResult(betterproto.Message):
    """Provides details of a Trend Analysis result."""

    summary_card: "TrendSummaryCardInfo" = betterproto.message_field(1)
    """Summary information for the trend detection analysis."""

    overall_trends: List["TrendAnalysisResultTrend"] = betterproto.message_field(2)
    """Metric level trends."""

    segments: List["TrendAnalysisResultSegment"] = betterproto.message_field(3)
    """Array of the segments in the trend."""


@dataclass(eq=False, repr=False)
class TrendAnalysisResultTrend(betterproto.Message):
    """Provides fields that describes the trend."""

    time_range: "TimeRange" = betterproto.message_field(1)
    """Inclusive start and exclusive end time range."""

    intercept: Optional[float] = betterproto.double_field(
        2, optional=True, group="_intercept"
    )
    """Y-intersept of the trend."""

    trend: Optional[float] = betterproto.double_field(3, optional=True, group="_trend")
    """Steepness of trend."""

    size: Optional[float] = betterproto.double_field(4, optional=True, group="_size")
    """
    The size (in percent) of this trend relative to the overall population.
    """


@dataclass(eq=False, repr=False)
class TrendAnalysisResultSegment(betterproto.Message):
    """Segment of an trend analysis run."""

    id: int = betterproto.int64_field(1)
    """Unique ID corresponding to each segment, unique per analysis run."""

    factors: Dict[str, "Factor"] = betterproto.map_field(
        2, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    """
    The factors that define this segment, represented as a map of Dimension to
    Value.
    """

    trends: List["TrendAnalysisResultTrend"] = betterproto.message_field(4)
    """Trends for the segment."""

    impact: Optional[float] = betterproto.message_field(
        5, wraps=betterproto.TYPE_DOUBLE
    )
    """
    How much this segment contributes to the overall value of the metric
    calculation.
    """


@dataclass(eq=False, repr=False)
class TimeRange(betterproto.Message):
    """TimeRange start and end details with inclusive start and end dates."""

    start_date_inclusive: datetime = betterproto.message_field(1)
    end_date_inclusive: datetime = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class Value(betterproto.Message):
    """Represent different possible primitive data types."""

    boolean_value: bool = betterproto.bool_field(1, group="value_type")
    integer_value: int = betterproto.int64_field(2, group="value_type")
    string_value: str = betterproto.string_field(3, group="value_type")
    float_value: float = betterproto.double_field(4, group="value_type")
    timestamp_value: datetime = betterproto.message_field(5, group="value_type")


@dataclass(eq=False, repr=False)
class Factor(betterproto.Message):
    """(Dimension, Value) pairs that define a segment."""

    value: "Value" = betterproto.message_field(1, group="factor_type")
    """Value, it is either string, int, boolean, float or timestamp type."""

    keyword: "FactorKeyword" = betterproto.message_field(2, group="factor_type")
    """Keyword in a text dimension."""

    bin: "FactorBin" = betterproto.message_field(3, group="factor_type")
    """bin of a numerical dimension."""


@dataclass(eq=False, repr=False)
class FactorKeyword(betterproto.Message):
    """Keyword FactorType."""

    keyword: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class FactorBin(betterproto.Message):
    """Bin FactorType."""

    lower_bound: Optional[float] = betterproto.message_field(
        1, wraps=betterproto.TYPE_DOUBLE
    )
    """The inclusive lower bound of the bin."""

    upper_bound: Optional[float] = betterproto.message_field(
        2, wraps=betterproto.TYPE_DOUBLE
    )
    """The exclusive upper bound of the bin."""

    lower_bound_percentile: Optional[float] = betterproto.message_field(
        3, wraps=betterproto.TYPE_DOUBLE
    )
    """The percentile of `lower_bound` within the factor's dimension."""

    upper_bound_percentile: Optional[float] = betterproto.message_field(
        4, wraps=betterproto.TYPE_DOUBLE
    )
    """The percentile of `upper_bound` within the factor's dimension."""


@dataclass(eq=False, repr=False)
class MetricsListRequest(betterproto.Message):
    """Request payload for get metrics."""

    pass


@dataclass(eq=False, repr=False)
class MetricsListResponse(betterproto.Message):
    """ListMetricsResponse provides list of Metrics."""

    metrics: List["Metric"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class UnitsConfig(betterproto.Message):
    type: "UnitsConfigUnitType" = betterproto.enum_field(1)
    label: Optional[str] = betterproto.message_field(2, wraps=betterproto.TYPE_STRING)
    scale: Optional[int] = betterproto.message_field(3, wraps=betterproto.TYPE_INT32)
    precision: Optional[int] = betterproto.message_field(
        4, wraps=betterproto.TYPE_INT32
    )
    currency: Optional[str] = betterproto.message_field(
        5, wraps=betterproto.TYPE_STRING
    )
    kmb: bool = betterproto.bool_field(6)


@dataclass(eq=False, repr=False)
class Metric(betterproto.Message):
    """Detailed information about a metric."""

    id: int = betterproto.uint64_field(1)
    """Metric id."""

    name: str = betterproto.string_field(2)
    """Metric name."""

    weight_dimension_name: Optional[str] = betterproto.message_field(
        3, wraps=betterproto.TYPE_STRING
    )
    """
    The name of the weight dimension. A weight dimension is used to increases
    the importance of a given row in an analysis.
    """

    time_dimension_name: Optional[str] = betterproto.message_field(
        4, wraps=betterproto.TYPE_STRING
    )
    """
    The name of metric's time dimension which represnts the date range of the
    metric.
    """

    desired_direction: "MetricDesiredDirection" = betterproto.enum_field(5)
    """
    Specifies whether the metric's goal is to increase or decrease the kpi
    value.
    """

    metric_dimension: "MetricMetricDimension" = betterproto.message_field(6)
    """The dimension which defines the metric's goal."""

    kpi_units_config: Optional["UnitsConfig"] = betterproto.message_field(
        7, optional=True, group="_kpi_units_config"
    )
    """The unit associated with the KDA metric."""

    type: "MetricMetricType" = betterproto.enum_field(8)
    """Type of metric calculation."""

    created_at: datetime = betterproto.message_field(9)
    """Timestamp when the metric was created."""

    dataset_id: int = betterproto.uint64_field(10)
    """Id of the metric data set."""


@dataclass(eq=False, repr=False)
class MetricMetricDimension(betterproto.Message):
    """A dimension in a metric."""

    name: str = betterproto.string_field(1)
    """The name of the dimension."""

    value: "Value" = betterproto.message_field(2)
    """Value, it is either string, int, boolean, float or timestamp type."""


@dataclass(eq=False, repr=False)
class AnalysisDimensionsListRequest(betterproto.Message):
    """Request for a list of dimensions for a given `analysis_id`."""

    analysis_id: int = betterproto.int64_field(1)
    """Unique ID corresponding to the analysis containing the dimensions."""

    is_selected: Optional[str] = betterproto.message_field(
        2, wraps=betterproto.TYPE_STRING
    )
    """
    Will return only active or non active dimensions for a given analysis.
    """


@dataclass(eq=False, repr=False)
class DataSetDimensionsListRequest(betterproto.Message):
    """Request for a list of dimensions for a given `dimension_id`."""

    dataset_id: int = betterproto.int64_field(1)
    """Unique ID corresponding to the dataset containing the dimensions."""


@dataclass(eq=False, repr=False)
class Dimension(betterproto.Message):
    """Represents a dimension (column) within a specfic `Dataset`."""

    name: str = betterproto.string_field(1)
    """
    A string literal corresponding to a column selected in the dataset. It is
    either a column name or a column alias for a computed SQL function over a
    column ( for example, `upper(email) as 'UPPER_EMAIL'` ex: `red` in `SELECT
    roja as red`.
    """

    dataset_id: int = betterproto.uint64_field(2)
    """Refers to the dataset that this dimension is associated with."""

    dimension_type: "SqlDataType" = betterproto.enum_field(3)
    """
    Refers to the column type of this dimension as it exists within the data
    warehouse
    """


@dataclass(eq=False, repr=False)
class AnalysisDimension(betterproto.Message):
    """Represents a dimension (column) within a specfic `analsyis`."""

    name: str = betterproto.string_field(1)
    """
    A string literal corresponding to a column selected in the dataset. It is
    either a column name or a column alias for a computed SQL function over a
    column ( for example, `upper(email) as 'UPPER_EMAIL'` ex: `red` in `SELECT
    roja as red`.
    """

    dimension_type: "SqlDataType" = betterproto.enum_field(2)
    """
    Refers to the column type of this dimension as it exists within the data
    warehouse
    """

    is_selected: bool = betterproto.bool_field(3)
    """Set to true if the dimension is part of the analysis."""


@dataclass(eq=False, repr=False)
class DataSetDimensionsListResponse(betterproto.Message):
    """
    DataSetDimensionsListResponse provides list of Dimensions for a given
    dataset.
    """

    dimensions: List["Dimension"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class AnalysisDimensionsListResponse(betterproto.Message):
    """
    AnalysisDimensionsListResponse provides list of Dimensions for a given
    analysis.
    """

    dimensions: List["AnalysisDimension"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class DataSourceListRequest(betterproto.Message):
    """Request payload for get datasources."""

    pass


@dataclass(eq=False, repr=False)
class DataSourceListResponse(betterproto.Message):
    """Response payload for get datasources."""

    data_sources: List["DataSource"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class DataSource(betterproto.Message):
    id: int = betterproto.uint64_field(1)
    """Id of a given data source."""

    name: str = betterproto.string_field(2)
    """Represents the table or query name of a data source."""

    data_source_type: "DataSourceDataSourceType" = betterproto.enum_field(3)
    """Type of the data source."""

    created_at: datetime = betterproto.message_field(4)
    """Time when the data source was created."""

    created_by: str = betterproto.string_field(5)
    """Data source creator's user email info."""

    connection_uri: str = betterproto.string_field(6)
    """JDBC connection URI to the data source location."""


@dataclass(eq=False, repr=False)
class DataSetsRequest(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class DataSetsResponse(betterproto.Message):
    datasets: List["Dataset"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class Dataset(betterproto.Message):
    """Dataset contains instructions on how to query a data source."""

    id: int = betterproto.uint64_field(1)
    """Id of a given dataset."""

    name: str = betterproto.string_field(2)
    """
    Represents the table name for DATASET_TYPE_TABLE or user-defined for
    DATASET_TYPE_QUERY.
    """

    dataset_type: "DatasetDatasetType" = betterproto.enum_field(3)
    """Dataset type represents how data has been obtained."""

    query_string: str = betterproto.string_field(4)
    """A SQL query string for a datasete of type query."""

    last_modified: datetime = betterproto.message_field(5)
    """Last time the data set was modified."""

    created_at: datetime = betterproto.message_field(6)
    """Time when the data set was created."""

    data_source_id: int = betterproto.uint64_field(7)
    """Data Source id of the data set."""


@dataclass(eq=False, repr=False)
class DuplicateAnalysisRequest(betterproto.Message):
    id: int = betterproto.uint64_field(1)
    """Analysis id to be duplicated"""

    name: str = betterproto.string_field(2)
    """optinal name for the new analysis"""


@dataclass(eq=False, repr=False)
class DuplicateAnalysisResponse(betterproto.Message):
    id: int = betterproto.uint64_field(1)
    """Newly created Analysis id."""


@dataclass(eq=False, repr=False)
class GetSegmentDataRequest(betterproto.Message):
    id: int = betterproto.uint64_field(1)
    """Segment id to get data for."""


@dataclass(eq=False, repr=False)
class GetSegmentDataResponse(betterproto.Message):
    query_string: str = betterproto.string_field(1)
    """query string that would result in the segment data."""


@dataclass(eq=False, repr=False)
class CreateDataSetRequest(betterproto.Message):
    dataset: "CreateDataSetRequestDataset" = betterproto.message_field(1)
    data_source_id: int = betterproto.uint64_field(2)


@dataclass(eq=False, repr=False)
class CreateDataSetRequestDataset(betterproto.Message):
    name: str = betterproto.string_field(1)
    """Name of the dataset."""

    query_string: str = betterproto.string_field(2)
    """A SQL query string for a datasete of type query."""


@dataclass(eq=False, repr=False)
class CreateDataSetResponse(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class GetProjectsListRequest(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class GetProjectsListResponse(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class GetProjectsListResponseListProjectResponse(betterproto.Message):
    projects: List["GetProjectsListResponseProject"] = betterproto.message_field(1)
    """List all projects."""


@dataclass(eq=False, repr=False)
class GetProjectsListResponseProject(betterproto.Message):
    """Provides detailed information about a project."""

    id: int = betterproto.uint64_field(1)
    """Project id."""

    name: str = betterproto.string_field(2)
    """Project name."""

    description: str = betterproto.string_field(3)
    """Project description."""

    created_at: datetime = betterproto.message_field(4)
    """Timestamp when the Project was created."""


@dataclass(eq=False, repr=False)
class GetProjectsAnalysesListRequest(betterproto.Message):
    id: int = betterproto.uint64_field(1)
    """Project id."""


@dataclass(eq=False, repr=False)
class GetProjectsAnalysesListResponse(betterproto.Message):
    analyses: List["Analysis"] = betterproto.message_field(1)
    """List of analyses associated with a project."""


@dataclass(eq=False, repr=False)
class TimeWindow(betterproto.Message):
    start_date: datetime = betterproto.message_field(1)
    """Start date inclsuvie."""

    end_date: datetime = betterproto.message_field(2)
    """End date exclusive."""


@dataclass(eq=False, repr=False)
class AnalysisDimensionRequest(betterproto.Message):
    name: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class CreateAnalysisRequest(betterproto.Message):
    project_id: int = betterproto.uint64_field(1)
    """Project id corresponding to the analysis."""

    name: str = betterproto.string_field(2)
    """The name of the analysis."""

    analysis: "CreateAnalysisRequestAnalysis" = betterproto.message_field(3)


@dataclass(eq=False, repr=False)
class CreateAnalysisRequestAnalysis(betterproto.Message):
    name: str = betterproto.string_field(1)
    """The name of the analysis."""

    type: "AnalysisType" = betterproto.enum_field(2)
    """The Type of the analysis."""

    time_dimension_name: Optional[str] = betterproto.message_field(
        3, wraps=betterproto.TYPE_STRING
    )
    """
    The name of metric's time dimension which represnts the date range of the
    metric.
    """

    metric_id: int = betterproto.uint64_field(4)
    """The metic id which the analysis depends on."""

    filter_expression: "Expression" = betterproto.message_field(5)
    """
    An Expression which would facilitate building a filter expression on the
    analysis.
    """

    time_range: "TimeWindow" = betterproto.message_field(6)
    """A time window the analysis should run on."""

    group_a_name: Optional[str] = betterproto.message_field(
        7, wraps=betterproto.TYPE_STRING
    )
    """The Group a name in a Group compare analysis."""

    group_b_name: Optional[str] = betterproto.message_field(
        8, wraps=betterproto.TYPE_STRING
    )
    """The Group b name in a Group compare analysis."""

    group_a_expression: "Expression" = betterproto.message_field(9)
    """
    A filter expression where group a is denfined in a Group compare analysis.
    """

    group_b_expression: "Expression" = betterproto.message_field(10)
    """
    A filter expression where group b is denfined in a Group compare analysis.
    """

    recent_range: "TimeWindow" = betterproto.message_field(11)
    """Recent time window range used for time compare analysis."""

    previous_range: "TimeWindow" = betterproto.message_field(12)
    """Previous time window range used for time compare analysis."""


@dataclass(eq=False, repr=False)
class CreateAnalysisResponse(betterproto.Message):
    name: str = betterproto.string_field(1)
    """The name of the analysis."""

    id: int = betterproto.int32_field(2)
    """Analysis id."""

    time_dimension_name: Optional[str] = betterproto.message_field(
        3, wraps=betterproto.TYPE_STRING
    )
    """
    The name of metric's time dimension which represnts the date range of the
    metric.
    """

    filter_expression: "Expression" = betterproto.message_field(4)
    """
    An Expression which would facilitate building a filter expression on the
    analysis.
    """

    metric_id: int = betterproto.int32_field(5)
    """The metic id which the analysis depends on."""

    time_range: "TimeWindow" = betterproto.message_field(6)
    """A time window the analysis should run on."""

    group_a_name: Optional[str] = betterproto.message_field(
        7, wraps=betterproto.TYPE_STRING
    )
    """The Group a name in a Group compare analysis."""

    group_b_name: Optional[str] = betterproto.message_field(
        8, wraps=betterproto.TYPE_STRING
    )
    """The Group b name in a Group compare analysis."""

    group_a_expression: "Expression" = betterproto.message_field(9)
    """
    A filter expression where group a is denfined in a Group compare analysis.
    """

    group_b_expression: "Expression" = betterproto.message_field(10)
    """
    A filter expression where group b is denfined in a Group compare analysis.
    """

    project_id: int = betterproto.int32_field(11)
    """Project id corresponding to the analysis."""

    type: "AnalysisType" = betterproto.enum_field(12)
    """The Type of the analysis."""

    created_at: datetime = betterproto.message_field(13)
    """Timestamp when the analysis was created."""

    application_url: str = betterproto.string_field(14)
    """
    Link to the live sisu analysis this represents. ex:
    vip.sisudata.com/projects/{id}/analysis/{id}
    """

    recent_range: "TimeWindow" = betterproto.message_field(15)
    """Recent time window range used for time compare analysis."""

    previous_range: "TimeWindow" = betterproto.message_field(16)
    """Previous time window range used for time compare analysis."""


@dataclass(eq=False, repr=False)
class ModifyAnalysisRequest(betterproto.Message):
    analysis_id: int = betterproto.uint64_field(1)
    analysis: "ModifyAnalysisRequestAnalysis" = betterproto.message_field(3)


@dataclass(eq=False, repr=False)
class ModifyAnalysisRequestAnalysis(betterproto.Message):
    name: Optional[str] = betterproto.string_field(1, optional=True, group="_name")
    """The name of the analysis."""

    time_dimension_name: Optional[Optional[str]] = betterproto.message_field(
        2, wraps=betterproto.TYPE_STRING, optional=True, group="_time_dimension_name"
    )
    """
    The name of metric's time dimension which represnts the date range of the
    metric.
    """

    filter_expression: Optional["Expression"] = betterproto.message_field(
        3, optional=True, group="_filter_expression"
    )
    """
    An Expression which would facilitate building a filter expression on the
    analysis.
    """

    time_range: Optional["TimeWindow"] = betterproto.message_field(
        4, optional=True, group="_time_range"
    )
    """A time window the analysis should run on."""

    group_a_name: Optional[Optional[str]] = betterproto.message_field(
        5, wraps=betterproto.TYPE_STRING, optional=True, group="_group_a_name"
    )
    """The Group a name in a Group compare analysis."""

    group_b_name: Optional[Optional[str]] = betterproto.message_field(
        6, wraps=betterproto.TYPE_STRING, optional=True, group="_group_b_name"
    )
    """The Group b name in a Group compare analysis."""

    group_a_expression: Optional["Expression"] = betterproto.message_field(
        7, optional=True, group="_group_a_expression"
    )
    """
    A filter expression where group a is denfined in a Group compare analysis.
    """

    group_b_expression: Optional["Expression"] = betterproto.message_field(
        8, optional=True, group="_group_b_expression"
    )
    """
    A filter expression where group b is denfined in a Group compare analysis.
    """

    recent_range: Optional["TimeWindow"] = betterproto.message_field(
        9, optional=True, group="_recent_range"
    )
    """Recent time window range used for time compare analysis."""

    previous_range: Optional["TimeWindow"] = betterproto.message_field(
        10, optional=True, group="_previous_range"
    )
    """Previous time window range used for time compare analysis."""


@dataclass(eq=False, repr=False)
class ModifyAnalysisResponse(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class UpdateAnalysisRequest(betterproto.Message):
    analysis_id: int = betterproto.uint64_field(1)
    name: str = betterproto.string_field(2)
    """The name of the analysis."""

    analysis: "UpdateAnalysisRequestAnalysis" = betterproto.message_field(3)


@dataclass(eq=False, repr=False)
class UpdateAnalysisRequestAnalysis(betterproto.Message):
    name: str = betterproto.string_field(1)
    """The name of the analysis."""

    type: "AnalysisType" = betterproto.enum_field(2)
    """The Type of the analysis."""

    time_dimension_name: Optional[str] = betterproto.message_field(
        3, wraps=betterproto.TYPE_STRING
    )
    """
    The name of metric's time dimension which represnts the date range of the
    metric.
    """

    filter_expression: "Expression" = betterproto.message_field(4)
    """
    An Expression which would facilitate building a filter expression on the
    analysis.
    """

    time_range: "TimeWindow" = betterproto.message_field(5)
    """A time window the analysis should run on."""

    group_a_name: Optional[str] = betterproto.message_field(
        6, wraps=betterproto.TYPE_STRING
    )
    """The Group a name in a Group compare analysis."""

    group_b_name: Optional[str] = betterproto.message_field(
        7, wraps=betterproto.TYPE_STRING
    )
    """The Group b name in a Group compare analysis."""

    group_a_expression: "Expression" = betterproto.message_field(8)
    """
    A filter expression where group a is denfined in a Group compare analysis.
    """

    group_b_expression: "Expression" = betterproto.message_field(9)
    """
    A filter expression where group b is denfined in a Group compare analysis.
    """

    recent_range: "TimeWindow" = betterproto.message_field(10)
    """Recent time window range used for time compare analysis."""

    previous_range: "TimeWindow" = betterproto.message_field(11)
    """Previous time window range used for time compare analysis."""


@dataclass(eq=False, repr=False)
class UpdateAnalysisResponse(betterproto.Message):
    name: str = betterproto.string_field(1)
    """The name of the analysis."""

    id: int = betterproto.uint64_field(2)
    """Analysis id."""

    time_dimension_name: Optional[str] = betterproto.message_field(
        3, wraps=betterproto.TYPE_STRING
    )
    """
    The name of metric's time dimension which represnts the date range of the
    metric.
    """

    filter_expression: "Expression" = betterproto.message_field(4)
    """
    An Expression which would facilitate building a filter expression on the
    analysis.
    """

    metric_id: int = betterproto.uint64_field(5)
    """The metic id which the analysis depends on."""

    time_range: "TimeWindow" = betterproto.message_field(6)
    """A time window the analysis should run on."""

    group_a_name: Optional[str] = betterproto.message_field(
        7, wraps=betterproto.TYPE_STRING
    )
    """The Group a name in a Group compare analysis."""

    group_b_name: Optional[str] = betterproto.message_field(
        8, wraps=betterproto.TYPE_STRING
    )
    """The Group b name in a Group compare analysis."""

    group_a_expression: "Expression" = betterproto.message_field(9)
    """
    A filter expression where group a is denfined in a Group compare analysis.
    """

    group_b_expression: "Expression" = betterproto.message_field(10)
    """
    A filter expression where group b is denfined in a Group compare analysis.
    """

    project_id: int = betterproto.uint64_field(11)
    """Project id corresponding to the analysis."""

    type: "AnalysisType" = betterproto.enum_field(12)
    """The Type of the analysis."""

    created_at: datetime = betterproto.message_field(13)
    """Timestamp when the analysis was created."""

    application_url: str = betterproto.string_field(14)
    """
    Link to the live sisu analysis this represents. ex:
    vip.sisudata.com/projects/{id}/analysis/{id}
    """

    recent_range: "TimeWindow" = betterproto.message_field(15)
    """Recent time window range used for time compare analysis."""

    previous_range: "TimeWindow" = betterproto.message_field(16)
    """Previous time window range used for time compare analysis."""


@dataclass(eq=False, repr=False)
class WaterfallStep(betterproto.Message):
    cumulative_impact_before_step: float = betterproto.double_field(1)
    """The cummulative value of impact prior to the waterfall step."""

    cumulative_impact_after_step: float = betterproto.double_field(2)
    """The cummulative value of impact after to the waterfall step."""

    overlapping_impact: float = betterproto.double_field(3)
    """The value of overlapping impact."""

    change_in_size: "WaterfallStepChangeInSize" = betterproto.message_field(4)
    change_in_type: "WaterfallStepChangeInType" = betterproto.message_field(5)
    factors: Dict[str, "Factor"] = betterproto.map_field(
        6, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    """Map of Factors for the waterfall step."""


@dataclass(eq=False, repr=False)
class WaterfallStepChangeInType(betterproto.Message):
    """The subgroup change in value."""

    subgroup_a: float = betterproto.double_field(1)
    """previous_period or group_a."""

    subgroup_b: float = betterproto.double_field(2)
    """recent_period or group_b."""


@dataclass(eq=False, repr=False)
class WaterfallStepChangeInSize(betterproto.Message):
    """The subgroup change in value."""

    subgroup_a: float = betterproto.double_field(1)
    """previous_period or group_a."""

    subgroup_b: float = betterproto.double_field(2)
    """recent_period or group_b."""


@dataclass(eq=False, repr=False)
class WaterfallAnalysisResponse(betterproto.Message):
    waterfall: List["WaterfallStep"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class WaterfallAnalysisRequest(betterproto.Message):
    id: int = betterproto.uint64_field(1)
    """Analysis id"""


class AnalysesServiceStub(betterproto.ServiceStub):
    async def analyses_list(
        self,
        analyses_list_request: "AnalysesListRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "AnalysesListResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/AnalysesList",
            analyses_list_request,
            AnalysesListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def run_analysis(
        self,
        run_analysis_request: "RunAnalysisRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "RunAnalysisResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/RunAnalysis",
            run_analysis_request,
            RunAnalysisResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def modify_analysis(
        self,
        modify_analysis_request: "ModifyAnalysisRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "ModifyAnalysisResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/ModifyAnalysis",
            modify_analysis_request,
            ModifyAnalysisResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def update_analysis(
        self,
        update_analysis_request: "UpdateAnalysisRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "UpdateAnalysisResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/UpdateAnalysis",
            update_analysis_request,
            UpdateAnalysisResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def waterfall_analysis(
        self,
        waterfall_analysis_request: "WaterfallAnalysisRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "WaterfallAnalysisResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/WaterfallAnalysis",
            waterfall_analysis_request,
            WaterfallAnalysisResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def analysis_run_results(
        self,
        analysis_run_results_request: "AnalysisRunResultsRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "AnalysisRunResultsResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/AnalysisRunResults",
            analysis_run_results_request,
            AnalysisRunResultsResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_analysis_filters(
        self,
        get_analysis_filters_request: "GetAnalysisFiltersRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetAnalysisFiltersResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/GetAnalysisFilters",
            get_analysis_filters_request,
            GetAnalysisFiltersResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def set_analysis_filters(
        self,
        set_analysis_filters_request: "SetAnalysisFiltersRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "SetAnalysisFiltersResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/SetAnalysisFilters",
            set_analysis_filters_request,
            SetAnalysisFiltersResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def analysis_dimensions_list(
        self,
        analysis_dimensions_list_request: "AnalysisDimensionsListRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "AnalysisDimensionsListResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/AnalysisDimensionsList",
            analysis_dimensions_list_request,
            AnalysisDimensionsListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def duplicate_analysis(
        self,
        duplicate_analysis_request: "DuplicateAnalysisRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "DuplicateAnalysisResponse":
        return await self._unary_unary(
            "/sisu.v1.api.AnalysesService/DuplicateAnalysis",
            duplicate_analysis_request,
            DuplicateAnalysisResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class MetricServiceStub(betterproto.ServiceStub):
    async def metrics_list(
        self,
        metrics_list_request: "MetricsListRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "MetricsListResponse":
        return await self._unary_unary(
            "/sisu.v1.api.MetricService/MetricsList",
            metrics_list_request,
            MetricsListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class DatasetServiceStub(betterproto.ServiceStub):
    async def data_sets(
        self,
        data_sets_request: "DataSetsRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "DataSetsResponse":
        return await self._unary_unary(
            "/sisu.v1.api.DatasetService/DataSets",
            data_sets_request,
            DataSetsResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def data_set_dimensions_list(
        self,
        data_set_dimensions_list_request: "DataSetDimensionsListRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "DataSetDimensionsListResponse":
        return await self._unary_unary(
            "/sisu.v1.api.DatasetService/DataSetDimensionsList",
            data_set_dimensions_list_request,
            DataSetDimensionsListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class DataSourcesServiceStub(betterproto.ServiceStub):
    async def data_source_list(
        self,
        data_source_list_request: "DataSourceListRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "DataSourceListResponse":
        return await self._unary_unary(
            "/sisu.v1.api.DataSourcesService/DataSourceList",
            data_source_list_request,
            DataSourceListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def create_data_set(
        self,
        create_data_set_request: "CreateDataSetRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "CreateDataSetResponse":
        return await self._unary_unary(
            "/sisu.v1.api.DataSourcesService/CreateDataSet",
            create_data_set_request,
            CreateDataSetResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class SegmentsServiceStub(betterproto.ServiceStub):
    async def get_segment_data(
        self,
        get_segment_data_request: "GetSegmentDataRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetSegmentDataResponse":
        return await self._unary_unary(
            "/sisu.v1.api.SegmentsService/GetSegmentData",
            get_segment_data_request,
            GetSegmentDataResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class ProjectsServiceStub(betterproto.ServiceStub):
    async def get_projects_list(
        self,
        get_projects_list_request: "GetProjectsListRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetProjectsListResponse":
        return await self._unary_unary(
            "/sisu.v1.api.ProjectsService/GetProjectsList",
            get_projects_list_request,
            GetProjectsListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_projects_analyses_list(
        self,
        get_projects_analyses_list_request: "GetProjectsAnalysesListRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetProjectsAnalysesListResponse":
        return await self._unary_unary(
            "/sisu.v1.api.ProjectsService/GetProjectsAnalysesList",
            get_projects_analyses_list_request,
            GetProjectsAnalysesListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class AnalysesServiceBase(ServiceBase):
    async def analyses_list(
        self, analyses_list_request: "AnalysesListRequest"
    ) -> "AnalysesListResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def run_analysis(
        self, run_analysis_request: "RunAnalysisRequest"
    ) -> "RunAnalysisResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def modify_analysis(
        self, modify_analysis_request: "ModifyAnalysisRequest"
    ) -> "ModifyAnalysisResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def update_analysis(
        self, update_analysis_request: "UpdateAnalysisRequest"
    ) -> "UpdateAnalysisResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def waterfall_analysis(
        self, waterfall_analysis_request: "WaterfallAnalysisRequest"
    ) -> "WaterfallAnalysisResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def analysis_run_results(
        self, analysis_run_results_request: "AnalysisRunResultsRequest"
    ) -> "AnalysisRunResultsResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_analysis_filters(
        self, get_analysis_filters_request: "GetAnalysisFiltersRequest"
    ) -> "GetAnalysisFiltersResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def set_analysis_filters(
        self, set_analysis_filters_request: "SetAnalysisFiltersRequest"
    ) -> "SetAnalysisFiltersResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def analysis_dimensions_list(
        self, analysis_dimensions_list_request: "AnalysisDimensionsListRequest"
    ) -> "AnalysisDimensionsListResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def duplicate_analysis(
        self, duplicate_analysis_request: "DuplicateAnalysisRequest"
    ) -> "DuplicateAnalysisResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_analyses_list(
        self, stream: "grpclib.server.Stream[AnalysesListRequest, AnalysesListResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.analyses_list(request)
        await stream.send_message(response)

    async def __rpc_run_analysis(
        self, stream: "grpclib.server.Stream[RunAnalysisRequest, RunAnalysisResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.run_analysis(request)
        await stream.send_message(response)

    async def __rpc_modify_analysis(
        self,
        stream: "grpclib.server.Stream[ModifyAnalysisRequest, ModifyAnalysisResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.modify_analysis(request)
        await stream.send_message(response)

    async def __rpc_update_analysis(
        self,
        stream: "grpclib.server.Stream[UpdateAnalysisRequest, UpdateAnalysisResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.update_analysis(request)
        await stream.send_message(response)

    async def __rpc_waterfall_analysis(
        self,
        stream: "grpclib.server.Stream[WaterfallAnalysisRequest, WaterfallAnalysisResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.waterfall_analysis(request)
        await stream.send_message(response)

    async def __rpc_analysis_run_results(
        self,
        stream: "grpclib.server.Stream[AnalysisRunResultsRequest, AnalysisRunResultsResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.analysis_run_results(request)
        await stream.send_message(response)

    async def __rpc_get_analysis_filters(
        self,
        stream: "grpclib.server.Stream[GetAnalysisFiltersRequest, GetAnalysisFiltersResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_analysis_filters(request)
        await stream.send_message(response)

    async def __rpc_set_analysis_filters(
        self,
        stream: "grpclib.server.Stream[SetAnalysisFiltersRequest, SetAnalysisFiltersResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.set_analysis_filters(request)
        await stream.send_message(response)

    async def __rpc_analysis_dimensions_list(
        self,
        stream: "grpclib.server.Stream[AnalysisDimensionsListRequest, AnalysisDimensionsListResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.analysis_dimensions_list(request)
        await stream.send_message(response)

    async def __rpc_duplicate_analysis(
        self,
        stream: "grpclib.server.Stream[DuplicateAnalysisRequest, DuplicateAnalysisResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.duplicate_analysis(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/sisu.v1.api.AnalysesService/AnalysesList": grpclib.const.Handler(
                self.__rpc_analyses_list,
                grpclib.const.Cardinality.UNARY_UNARY,
                AnalysesListRequest,
                AnalysesListResponse,
            ),
            "/sisu.v1.api.AnalysesService/RunAnalysis": grpclib.const.Handler(
                self.__rpc_run_analysis,
                grpclib.const.Cardinality.UNARY_UNARY,
                RunAnalysisRequest,
                RunAnalysisResponse,
            ),
            "/sisu.v1.api.AnalysesService/ModifyAnalysis": grpclib.const.Handler(
                self.__rpc_modify_analysis,
                grpclib.const.Cardinality.UNARY_UNARY,
                ModifyAnalysisRequest,
                ModifyAnalysisResponse,
            ),
            "/sisu.v1.api.AnalysesService/UpdateAnalysis": grpclib.const.Handler(
                self.__rpc_update_analysis,
                grpclib.const.Cardinality.UNARY_UNARY,
                UpdateAnalysisRequest,
                UpdateAnalysisResponse,
            ),
            "/sisu.v1.api.AnalysesService/WaterfallAnalysis": grpclib.const.Handler(
                self.__rpc_waterfall_analysis,
                grpclib.const.Cardinality.UNARY_UNARY,
                WaterfallAnalysisRequest,
                WaterfallAnalysisResponse,
            ),
            "/sisu.v1.api.AnalysesService/AnalysisRunResults": grpclib.const.Handler(
                self.__rpc_analysis_run_results,
                grpclib.const.Cardinality.UNARY_UNARY,
                AnalysisRunResultsRequest,
                AnalysisRunResultsResponse,
            ),
            "/sisu.v1.api.AnalysesService/GetAnalysisFilters": grpclib.const.Handler(
                self.__rpc_get_analysis_filters,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetAnalysisFiltersRequest,
                GetAnalysisFiltersResponse,
            ),
            "/sisu.v1.api.AnalysesService/SetAnalysisFilters": grpclib.const.Handler(
                self.__rpc_set_analysis_filters,
                grpclib.const.Cardinality.UNARY_UNARY,
                SetAnalysisFiltersRequest,
                SetAnalysisFiltersResponse,
            ),
            "/sisu.v1.api.AnalysesService/AnalysisDimensionsList": grpclib.const.Handler(
                self.__rpc_analysis_dimensions_list,
                grpclib.const.Cardinality.UNARY_UNARY,
                AnalysisDimensionsListRequest,
                AnalysisDimensionsListResponse,
            ),
            "/sisu.v1.api.AnalysesService/DuplicateAnalysis": grpclib.const.Handler(
                self.__rpc_duplicate_analysis,
                grpclib.const.Cardinality.UNARY_UNARY,
                DuplicateAnalysisRequest,
                DuplicateAnalysisResponse,
            ),
        }


class MetricServiceBase(ServiceBase):
    async def metrics_list(
        self, metrics_list_request: "MetricsListRequest"
    ) -> "MetricsListResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_metrics_list(
        self, stream: "grpclib.server.Stream[MetricsListRequest, MetricsListResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.metrics_list(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/sisu.v1.api.MetricService/MetricsList": grpclib.const.Handler(
                self.__rpc_metrics_list,
                grpclib.const.Cardinality.UNARY_UNARY,
                MetricsListRequest,
                MetricsListResponse,
            ),
        }


class DatasetServiceBase(ServiceBase):
    async def data_sets(
        self, data_sets_request: "DataSetsRequest"
    ) -> "DataSetsResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def data_set_dimensions_list(
        self, data_set_dimensions_list_request: "DataSetDimensionsListRequest"
    ) -> "DataSetDimensionsListResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_data_sets(
        self, stream: "grpclib.server.Stream[DataSetsRequest, DataSetsResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.data_sets(request)
        await stream.send_message(response)

    async def __rpc_data_set_dimensions_list(
        self,
        stream: "grpclib.server.Stream[DataSetDimensionsListRequest, DataSetDimensionsListResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.data_set_dimensions_list(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/sisu.v1.api.DatasetService/DataSets": grpclib.const.Handler(
                self.__rpc_data_sets,
                grpclib.const.Cardinality.UNARY_UNARY,
                DataSetsRequest,
                DataSetsResponse,
            ),
            "/sisu.v1.api.DatasetService/DataSetDimensionsList": grpclib.const.Handler(
                self.__rpc_data_set_dimensions_list,
                grpclib.const.Cardinality.UNARY_UNARY,
                DataSetDimensionsListRequest,
                DataSetDimensionsListResponse,
            ),
        }


class DataSourcesServiceBase(ServiceBase):
    async def data_source_list(
        self, data_source_list_request: "DataSourceListRequest"
    ) -> "DataSourceListResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def create_data_set(
        self, create_data_set_request: "CreateDataSetRequest"
    ) -> "CreateDataSetResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_data_source_list(
        self,
        stream: "grpclib.server.Stream[DataSourceListRequest, DataSourceListResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.data_source_list(request)
        await stream.send_message(response)

    async def __rpc_create_data_set(
        self,
        stream: "grpclib.server.Stream[CreateDataSetRequest, CreateDataSetResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.create_data_set(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/sisu.v1.api.DataSourcesService/DataSourceList": grpclib.const.Handler(
                self.__rpc_data_source_list,
                grpclib.const.Cardinality.UNARY_UNARY,
                DataSourceListRequest,
                DataSourceListResponse,
            ),
            "/sisu.v1.api.DataSourcesService/CreateDataSet": grpclib.const.Handler(
                self.__rpc_create_data_set,
                grpclib.const.Cardinality.UNARY_UNARY,
                CreateDataSetRequest,
                CreateDataSetResponse,
            ),
        }


class SegmentsServiceBase(ServiceBase):
    async def get_segment_data(
        self, get_segment_data_request: "GetSegmentDataRequest"
    ) -> "GetSegmentDataResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_segment_data(
        self,
        stream: "grpclib.server.Stream[GetSegmentDataRequest, GetSegmentDataResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_segment_data(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/sisu.v1.api.SegmentsService/GetSegmentData": grpclib.const.Handler(
                self.__rpc_get_segment_data,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetSegmentDataRequest,
                GetSegmentDataResponse,
            ),
        }


class ProjectsServiceBase(ServiceBase):
    async def get_projects_list(
        self, get_projects_list_request: "GetProjectsListRequest"
    ) -> "GetProjectsListResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_projects_analyses_list(
        self, get_projects_analyses_list_request: "GetProjectsAnalysesListRequest"
    ) -> "GetProjectsAnalysesListResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_projects_list(
        self,
        stream: "grpclib.server.Stream[GetProjectsListRequest, GetProjectsListResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_projects_list(request)
        await stream.send_message(response)

    async def __rpc_get_projects_analyses_list(
        self,
        stream: "grpclib.server.Stream[GetProjectsAnalysesListRequest, GetProjectsAnalysesListResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_projects_analyses_list(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/sisu.v1.api.ProjectsService/GetProjectsList": grpclib.const.Handler(
                self.__rpc_get_projects_list,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetProjectsListRequest,
                GetProjectsListResponse,
            ),
            "/sisu.v1.api.ProjectsService/GetProjectsAnalysesList": grpclib.const.Handler(
                self.__rpc_get_projects_analyses_list,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetProjectsAnalysesListRequest,
                GetProjectsAnalysesListResponse,
            ),
        }
