Source code for ppc_robot_lib.sklik.types

from __future__ import annotations

from enum import IntEnum, Enum
from ppc_robot_lib.utils.transformation import Transformation
from ppc_robot_lib.utils.types import LabeledEnum


class CategoryEnum(Enum):
    @classmethod
    def transform(cls, value):
        if value is None:
            return None
        try:
            return cls(value)
        except ValueError:
            item = getattr(cls, value)
            if item is not None:
                return item
            else:
                return None

    @classmethod
    def get_transformation(cls):
        if not hasattr(cls, '_transformation'):

            class CategoryEnumTransformation(Transformation):
                @staticmethod
                def to_internal_value(value):
                    return cls.transform(value)

                @staticmethod
                def from_internal_value(value):
                    if isinstance(value, str):
                        return value
                    elif isinstance(value, cls):
                        return value.name
                    elif value is None:
                        return None
                    else:
                        return str(value)

            cls._transformation = CategoryEnumTransformation
        return cls._transformation

    def __gt__(self, other):
        if self.__class__ is other.__class__:
            return self.value > other.value
        raise NotImplemented

    def __ge__(self, other):
        if self.__class__ is other.__class__:
            return self.value >= other.value
        raise NotImplemented

    def __lt__(self, other):
        if self.__class__ is other.__class__:
            return self.value < other.value
        raise NotImplemented

    def __le__(self, other):
        if self.__class__ is other.__class__:
            return self.value <= other.value
        raise NotImplemented


[docs] class Granularity(IntEnum): TOTAL = 0 """Sum for the whole date-range.""" YEARLY = 1 """Per-year granularity.""" QUARTERLY = 2 """Per year-quarter granularity.""" MONTHLY = 3 """Per month granularity.""" WEEKLY = 4 """Per-week granularity.""" DAILY = 5 """Per-day granularity.""" def combine(self, other: Granularity | None): if other and self != other: if (other == Granularity.WEEKLY and self > Granularity.TOTAL) or ( self == Granularity.WEEKLY and other > Granularity.TOTAL ): return self.DAILY elif other > self: return other return self @property def api_value(self): return self.name.lower()
class StatusEnum(LabeledEnum, CategoryEnum): ACTIVE = 'active' NOACTIVE = 'noactive' SUSPEND = 'suspend' def get_labels(self): return { StatusEnum.ACTIVE: 'Active', StatusEnum.NOACTIVE: 'Not Active', StatusEnum.SUSPEND: 'Suspended', } class GroupMixedStatus(LabeledEnum, CategoryEnum): ACTIVE = 'active' NOACTIVE = 'noactive' SUSPEND = 'suspend' DELETED = 'deleted' def get_labels(self): return { GroupMixedStatus.ACTIVE: 'Active', GroupMixedStatus.NOACTIVE: 'Not Active', GroupMixedStatus.SUSPEND: 'Suspended', GroupMixedStatus.DELETED: 'Deleted', } class CampaignMixedStatus(LabeledEnum, CategoryEnum): ACTIVE = 'active' ACTIVE_EXHAUSTED_DAY_BUDGET = 'active-exhausted_day_budget' ACTIVE_EXPIRED_BUDGET = 'active-expired_budget' ACTIVE_EXPIRED_CLICKS = 'active-expired_clicks' ACTIVE_EXPIRED_TIME = 'active-expired_time' ACTIVE_LOW_BUDGET = 'active-low_budget' ACTIVE_WAITING = 'active-waiting' SUSPENDED = 'suspended' DELETED = 'deleted' def get_labels(self): return { CampaignMixedStatus.ACTIVE: 'Active', CampaignMixedStatus.ACTIVE_EXHAUSTED_DAY_BUDGET: 'Active - Exhausted Daily Budget', CampaignMixedStatus.ACTIVE_EXPIRED_BUDGET: 'Active - Expired Budget', CampaignMixedStatus.ACTIVE_EXPIRED_CLICKS: 'Active - Expired Clicks', CampaignMixedStatus.ACTIVE_EXPIRED_TIME: 'Active - Expired Time', CampaignMixedStatus.ACTIVE_LOW_BUDGET: 'Active - Low Budget', CampaignMixedStatus.ACTIVE_WAITING: 'Active - Waiting', CampaignMixedStatus.SUSPENDED: 'Suspended', CampaignMixedStatus.DELETED: 'Deleted', } class DeviceType(LabeledEnum, CategoryEnum): PHONE = 'devicePhone' DESKTOP = 'deviceDesktop' TABLET = 'deviceTablet' OTHER = 'deviceOther' def get_labels(self): return { DeviceType.PHONE: 'Phone', DeviceType.DESKTOP: 'Desktop', DeviceType.TABLET: 'Tablet', DeviceType.OTHER: 'Other', } class CampaignAdSelection(LabeledEnum, CategoryEnum): COS = 'cos' CPA = 'cpa' RANDOM = 'random' WEIGHTED = 'weighted' def get_labels(self): return { CampaignAdSelection.COS: 'COS', CampaignAdSelection.CPA: 'CPA', CampaignAdSelection.RANDOM: 'Random', CampaignAdSelection.WEIGHTED: 'Weighted', } class NetworkFilter(LabeledEnum, CategoryEnum): FULLTEXT_ONLY = 'fulltext_only' CONTEXT_ONLY = 'context_only' CONTEXT_AND_FULLTEXT = 'context_and_fulltext' def get_labels(self): return { NetworkFilter.FULLTEXT_ONLY: 'Fulltext Only', NetworkFilter.CONTEXT_ONLY: 'Context Only', NetworkFilter.CONTEXT_AND_FULLTEXT: 'Both Context and Fulltext', } class MatchType(LabeledEnum, CategoryEnum): BROAD = 'broad' PHRASE = 'phrase' EXACT = 'exact' def get_labels(self): return { MatchType.BROAD: 'Broad', MatchType.PHRASE: 'Phrase', MatchType.EXACT: 'Exact', } class KeywordMixedStatus(LabeledEnum, CategoryEnum): ACTIVE = 'active' ACTIVE_NOACTIVE = 'active-noactive' ACTIVE_NEVER = 'active-never' ACTIVE_DISABLED = 'active-disabled' SUSPENDED = 'suspended' DELETED = 'deleted' def get_labels(self): return { KeywordMixedStatus.ACTIVE: 'Active', KeywordMixedStatus.ACTIVE_NOACTIVE: 'Suspended by system - change CPC', KeywordMixedStatus.ACTIVE_NEVER: 'Suspended by system - cannot be triggered', KeywordMixedStatus.ACTIVE_DISABLED: 'Suspended by system - prohibited keyword', KeywordMixedStatus.SUSPENDED: 'Suspended', KeywordMixedStatus.DELETED: 'Deleted', } class EroticSensitivity(CategoryEnum): HARMLESS = 'harmless' EROTIC = 'erotic' PORN = 'porn' class AdStatusEnum(CategoryEnum): NEW = 'new' WAITING = 'waiting' ALLOW = 'allow' DENY = 'deny' NOACTIVE = 'noactive' DENY_EXCESS_PUNCTUATION = 'deny_excess_punctuation' DENY_BAD_UPPERCASE_USAGE = 'deny_bad_uppercase_usage' DENY_EXCLAMATION_MARK_IN_TITLE = 'deny_exclamation_mark_in_title' DENY_EXCESS_WORDS_DUPLICATION = 'deny_excess_words_duplication' DENY_DISALLOWED_LANGUAGE = 'deny_disallowed_language' DENY_NONSENSICAL_TEXT = 'deny_nonsensical_text' DENY_SUPERLATIVE_IN_TEXT = 'deny_superlative_in_text' DENY_GENERAL_PHRASE = 'deny_general_phrase' DENY_UNMATCHED_DOMAIN = 'deny_unmatched_domain' DENY_NONEXISTENT_DOMAIN = 'deny_nonexistent_domain' DENY_INVALID_URL = 'deny_invalid_url' DENY_URL_UNDER_CONSTRUCTION = 'deny_url_under_construction' DENY_UNSUITABLE_URL = 'deny_unsuitable_url' DENY_FALSE_ADVERTISING = 'deny_false_advertising' DENY_MENTION_OF_COMPETITION = 'deny_mention_of_competition' DENY_NOT_CONJOINT_WITH_TARGET_PAGE = 'deny_not_conjoint_with_target_page' DENY_NOT_CONJOINT_WITH_KEYWORDS = 'deny_not_conjoint_with_keywords' DENY_UNVERIFIABLE_PRICES = 'deny_unverifiable_prices' DENY_EROTIC_CONTENT = 'deny_erotic_content' DENY_DISALLOWED_CONTENT = 'deny_disallowed_content' DENY_TRADEMARK = 'deny_trademark' DENY_NOT_DIACRITICAL_TEXT = 'deny_not_diacritical_text' DENY_MISSING_SPACE = 'deny_missing_space' DENY_AVERMENT_OF_UNIQUENESS = 'deny_averment_of_uniqueness' DENY_DISCOUNT_WITH_REFFERED_VALUE = 'deny_discount_with_reffered_value' DENY_UNTYPICAL_ABBREVIATION = 'deny_untypical_abbreviation' DENY_TYPING_OR_GRAMMATICAL_ERROR = 'deny_typing_or_grammatical_error' DENY_IMPENETRABLE_WORDS_DIVIDING = 'deny_impenetrable_words_dividing' DENY_PROBLEM_WITH_PUNCTUATION = 'deny_problem_with_punctuation' NOACTIVE_UNSUPPORTED_SIZE = 'noactive_unsupported_size' class AdTypeEnum(LabeledEnum, CategoryEnum): STA = 'sta' ETA = 'eta' COMBINED = 'combined' BRANDING = 'branding' VIDEO = 'video' BUMPER = 'bumper' UNKNOWN = 'unknown' def get_labels(self): return { AdTypeEnum.STA: 'Standard Text Ad', AdTypeEnum.ETA: 'Extended Text Ad', AdTypeEnum.COMBINED: 'Combined Ad', AdTypeEnum.BRANDING: 'Branding Ad', AdTypeEnum.VIDEO: 'Video', AdTypeEnum.BUMPER: 'Bumper', AdTypeEnum.UNKNOWN: 'Unknown', } @classmethod def transform(cls, value): if value == 'text': return cls.STA try: return super().transform(value) except (KeyError, AttributeError): return cls.UNKNOWN class AdMixedStatus(CategoryEnum): ACTIVE = 'active' WAITING = 'waiting' ACTIVE_EROTIC = 'active-erotic' ACTIVE_PORN = 'active-porn' DENY = 'deny' SUSPENDED = 'suspended' DELETED = 'deleted' class SitelinkType(LabeledEnum, CategoryEnum): NULL = 'null' GROUP = 'group' CAMPAIGN = 'campaign' def get_labels(self): return { SitelinkType.NULL: 'Not Assigned', SitelinkType.GROUP: 'Ad Group', SitelinkType.CAMPAIGN: 'Campaign', } class SitelinkStatus(CategoryEnum): NEW = 'new' WAITING = 'waiting' ALLOW = 'allow' DENY = 'deny' NOACTIVE = 'noactive' DENY_EXCESS_PUNCTUATION = 'deny_excess_punctuation' DENY_BAD_UPPERCASE_USAGE = 'deny_bad_uppercase_usage' DENY_EXCLAMATION_MARK_IN_TITLE = 'deny_exclamation_mark_in_title' DENY_EXCESS_WORDS_DUPLICATION = 'deny_excess_words_duplication' DENY_DISALLOWED_LANGUAGE = 'deny_disallowed_language' DENY_NONSENSICAL_TEXT = 'deny_nonsensical_text' DENY_SUPERLATIVE_IN_TEXT = 'deny_superlative_in_text' DENY_GENERAL_PHRASE = 'deny_general_phrase' DENY_UNMATCHED_DOMAIN = 'deny_unmatched_domain' DENY_NONEXISTENT_DOMAIN = 'deny_nonexistent_domain' DENY_INVALID_URL = 'deny_invalid_url' DENY_URL_UNDER_CONSTRUCTION = 'deny_url_under_construction' DENY_UNSUITABLE_URL = 'deny_unsuitable_url' DENY_FALSE_ADVERTISING = 'deny_false_advertising' DENY_MENTION_OF_COMPETITION = 'deny_mention_of_competition' DENY_NOT_CONJOINT_WITH_TARGET_PAGE = 'deny_not_conjoint_with_target_page' DENY_NOT_CONJOINT_WITH_KEYWORDS = 'deny_not_conjoint_with_keywords' DENY_UNVERIFIABLE_PRICES = 'deny_unverifiable_prices' DENY_EROTIC_CONTENT = 'deny_erotic_content' DENY_DISALLOWED_CONTENT = 'deny_disallowed_content' DENY_TRADEMARK = 'deny_trademark' DENY_NOT_DIACRITICAL_TEXT = 'deny_not_diacritical_text' DENY_MISSING_SPACE = 'deny_missing_space' DENY_AVERMENT_OF_UNIQUENESS = 'deny_averment_of_uniqueness' DENY_DISCOUNT_WITH_REFFERED_VALUE = 'deny_discount_with_reffered_value' DENY_UNTYPICAL_ABBREVIATION = 'deny_untypical_abbreviation' DENY_TYPING_OR_GRAMMATICAL_ERROR = 'deny_typing_or_grammatical_error' DENY_IMPENETRABLE_WORDS_DIVIDING = 'deny_impenetrable_words_dividing' DENY_PROBLEM_WITH_PUNCTUATION = 'deny_problem_with_punctuation' NOACTIVE_UNSUPPORTED_SIZE = 'noactive_unsupported_size' class NegativeMatchType(LabeledEnum, CategoryEnum): NEGATIVE_BROAD = 'negative_broad' NEGATIVE_PHRASE = 'negative_phrase' NEGATIVE_EXACT = 'negative_exact' def get_labels(self): return { NegativeMatchType.NEGATIVE_BROAD: 'Negative Broad', NegativeMatchType.NEGATIVE_PHRASE: 'Negative Phrase', NegativeMatchType.NEGATIVE_EXACT: 'Negative Exact', }