Пример #1
0
    def check_parameters(self):
        '''
        @summary: Check that all the parameters given, match the ones set as
        required and optional for this block.
        @raise WFBridgeException: if there is a mismatch with the parameters.
        '''
        all_params = []
        for pv in self.parameters.itervalues():
            all_params.extend(pv.keys())
        all_params = set(all_params)

        req = set(self.required_parameters)
        opt = set(self.optional_parameters)

        # Check all required parameters are set
        if not req.issubset(all_params):
            missing = ",".join(req - all_params)
            err = "Missing required parameters {}".format(missing)
            raise WFBrigeException(err)

        # Now check that the parameters that are not required are optional
        if not (all_params - req).issubset(opt):
            unused_parameters = ",".join(all_params - req - opt)
            err = "{} have been specified but are not required nor optional"
            raise WFBrigeException(err.format(unused_parameters))

        for block in self.blocks:
            block.check_parameters()
    def _check_viability(self):
        def check_not_none(name, value):
            if value is None:
                raise WFBrigeException("{} is required".format(name))

        if self.exclude_html_validation:
            check_not_none("ecm_html", self.ecm_html)
        else:
            if self.html is None and self.html_zip is None:
                err = "At least a zip or an html should be provided"
                raise WFBrigeException(err)

            if self.html is not None and self.html_zip is not None:
                err = "Only a zip or an html should be provided"
                raise WFBrigeException(err)

            if len(self.test_seed_lists) > 0:
                check_not_none("seeds_provider", self.seeds_provider.name)
                check_not_none("seeds_sender_name",
                               self.seeds_provider.sender_name)
                check_not_none("seeds_sender_email",
                               self.seeds_provider.sender_email)

        check_not_none("subject", self.subject)
        check_not_none("email_creative_id", self.email_creative_id)

        check_not_none("audience_provider", self.audience_provider.name)
        check_not_none("audience_sender_name",
                       self.audience_provider.sender_name)
        check_not_none("audience_sender_email",
                       self.audience_provider.sender_email)
Пример #3
0
    def __task_from_name(self, task_name, tasks, prj):
        # Task identifier is a task number in the project block
        if type(task_name) == int:
            if len(tasks) < task_name:
                tmpl = prj.get_template_id()
                err = "Project Template {} has {} tasks. Task {} referenced " \
                      "from task parameter values."
                err = err.format(tmpl, len(tasks), task_name)
                raise WFBrigeException(err)
            return tasks[task_name - 1]

        # Task is being identified by its name
        mtasks = [t for t in tasks if t.name == task_name]
        if len(mtasks) == 1:
            return mtasks[0]
        elif len(mtasks) == 0:
            tmpl = prj.get_template_id()
            err = "Project Template {} does not have task name {} referenced " \
                  "from task parameter values."
            err = err.format(tmpl, task_name)
            raise WFBrigeException(err)
        else:
            tmpl = prj.get_template_id()
            err = "Project Template {} has more than one task named as {}"
            err = err.format(tmpl, task_name)
            raise WFBrigeException(err)
 def __fullfill_project_type(self):
     '''
     @summary: Fullfill self.project_type based on the project that will be
     cancel (self.wf_project_id)
     @raise WFBridgeException: if the project has an unsupported project
     type to cancel.
     '''
     prj = WFProject(self.wf, self.wf_project_id)
     params = prj.get_param_values()
     if "Project Type" not in params:
         WFBrigeException("Unknown Project Type - {} is missing Project "
                          "Type custom form field".format(prj))
     if params["Project Type"] not in self.supported_project_types:
         WFBrigeException("Project Type {} not supported for canceling "
                          "project {}".format(prj))
     self.project_type = params["Project Type"]
 def check_file_extension(name,
                          file_name,
                          allowed_extensions=(".html", )):
     if not file_name.lower().endswith(allowed_extensions):
         raise WFBrigeException(
             "{}: {} file hasn't an allowed extensions ({})".format(
                 name, file_name, ",".join(allowed_extensions)))
 def check_length(field_name,
                  collection,
                  min_length=0,
                  max_length=sys.maxint):
     if len(collection) < min_length or len(collection) > max_length:
         raise WFBrigeException(
             "{}: length ({}) is not between {} to {}".format(
                 field_name, len(collection), min_length, max_length))
Пример #7
0
    def set_audience_identifier(self, audience_identifier):
        if audience_identifier not in self.AUDIENCE_FILE_INDENTIFIERS:
            m = "Invalid audience identifier {}. Possible values are {}"
            err = m.format(audience_identifier,
                           ",".join(self.AUDIENCE_FILE_INDENTIFIERS))
            raise WFBrigeException(err)

        self.audience_identifier = audience_identifier
        return self
 def add_ad_group(self, ad_group):
     """
     Ad Group kwargs:
     {}
     
     Creative common kwargs:
     {}
     """.format(self.ad_group_fields, self.creative_common_fields)
     allowed_keys = self.ad_group_fields
     for k, v in ad_group.items():
         if k not in allowed_keys:
             raise WFBrigeException('Invalid Key {}'.format(k))
         elif k == 'creatives':
             for creative in v:
                 creative_allowed_keys = self.creative_type_allowed_fields[creative['creative_type']]
                 for creative_key, creative_value in creative.items():
                     if creative_key not in creative_allowed_keys:
                         raise WFBrigeException('Invalid Creative Key {}'.format(creative_key))
     self._ad_groups.append(ad_group)
Пример #9
0
    def set_suppression_type(self, suppression_type):
        '''
        @param suppression_type: one_per_person, one_per_household
        '''
        if suppression_type not in self.SUPPRESSION_TYPES:
            m = "Invalid suppression type {}. Possible values are {}"
            raise WFBrigeException(
                m.format(suppression_type, ",".join(self.SUPPRESSION_TYPES)))

        self.suppression_type = suppression_type
        return self
Пример #10
0
    def _check_viability(self):
        if self.project_type is None:
            m = "You must specify the type of data project to be created (use"\
                " set_b2c or set_match_and_export)"
            raise WFBrigeException(m)

        if self.project_type == "b2c":
            self._check_viability_b2c()
        elif self.project_type == "m&e":
            self._check_viability_match_and_export()
        else:
            raise Exception("Invalid data project type")
    def build(self):
        """
        @summary: build the Workfront project.
        @raise WFBrigeException
        @return: WFProject object
        """
        if not self._ad_groups:
            raise WFBrigeException('The project does not have any ad_groups. Please use add_ad_group to add them.')

        project = WFProjectSocialContainer(self.project_name)

        # Blocks
        order_review_block = WFSocialOrderReviewBlock()
        data_block = WFSocialDataBlock()

        setup_block = WFSocialSetupBlock()
        setup_block.campaign_title = self._campaign_title
        setup_block.fb_page_id = self._fb_page_id
        setup_block.fb_ig_acc_id = self._fb_ig_acc_id
        setup_block.fb_advertising_objective = self._fb_advertising_objective
        setup_block.fb_offer = self._fb_offer
        setup_block.fb_apply_block_list = self._fb_apply_block_list

        ad_group_setup_blocks = []
        for ad_group in self._ad_groups:
            ad_group_setup_block = WFSocialAdGroupSetupBlock()
            for creative in ad_group['creatives']:
                creative_upload_dict = {k: creative[k] for k
                                        in self.creative_type_allowed_fields[creative['creative_type']]
                                        if k in creative}
                ad_group_setup_block.add_creative(**creative_upload_dict)
            ad_group_setup_block.add_ad_group(**ad_group)
            ad_group_setup_blocks.append(ad_group_setup_block)

        launch_block = WFSocialLaunchBlock()
        launch_block.provider = self._provider

        project_blocks = [
            order_review_block,
            data_block,
            setup_block
        ]
        project_blocks.extend(ad_group_setup_blocks)
        project_blocks.append(launch_block)

        [project.append(block) for block in project_blocks]
        parser = WFBlockParser(self.wf)
        wf_project = parser.create(project)
        return wf_project
Пример #12
0
def set_kwargs(obj, kwargs, exclude=[]):
    """If the argument exists in the object, it is set to the value in
    the kwargs dict.
    Excluded values are ignored.
    """
    for k, v in kwargs.items():
        if k in exclude:
            continue
        try:
            getattr(obj, k)
        except AttributeError:
            raise WFBrigeException('Invalid Key: {}'.format(k))
        else:
            setattr(obj, k, v)
    return obj
Пример #13
0
    def add_suppression_file(self, file_path, suppression_file_type):
        '''
        @param file_path: s3 file path
        @param supression_type: bridge_id, email, maid, md5, postal
        '''
        if suppression_file_type not in self.SUPPRESSION_FILE_TYPES:
            m = "Invalid suppression file type {}. Possible values are {}"
            err = m.format(suppression_file_type,
                           ",".join(self.SUPPRESSION_FILE_TYPES))
            raise WFBrigeException(err)

        kv = {
            "file_path": file_path,
            "suppression_file_type": suppression_file_type
        }
        self.suppression_files.append(kv)
        return self
    def build(self):
        """
        @summary: Build the WF project.
        @raise WFBridgeException: if the combination of parameters set in the
        builder are not compatible (like missing parameters).
        @return: a WFProject object.
        """
        project = CWPushContainer(self.project_name)
        # Project
        project.bridge_order_id = self.bridge_order_id
        project.order_name = self.order_name
        project.partner_name = self.partner_name
        project.industry = self.industry
        project.html_link = self.html_link
        project.banner_link = self.banner_link
        project.start_date = self.start_date
        project.target_volume = self.target_volume
        project.overage = self.overage
        project.geo_target = self.geo_target
        project.geo_target_state = self.geo_target_state
        project.deployment_file_link = self.deployment_file_link
        project.deployment_file_segment = self.deployment_file_segment
        project.click_tier = self.click_tier
        project.open_tier = self.open_tier
        project.cw_tool_link = self.cw_tool_link
        project.duration = self.duration
        if self.purl_processing_enabled is not None:
            if type(self.purl_processing_enabled) == bool:
                project.purl_processing_enabled = self.purl_processing_enabled
            else:
                raise WFBrigeException('PURL Processing Enabled allowed values: True or False')
        # Block
        block = CWPushBlock()
        project.append(block)

        parser = WFBlockParser(self.wf)
        wf_project = parser.create(project)
        return wf_project
Пример #15
0
 def add_creative(self, **kwargs):
     n_creatives = len(self._creatives)
     if n_creatives == self.max_creatives:
         raise WFBrigeException('The maximum number of creatives for a Carousel or Slideshow is {}'
                                .format(n_creatives))
     creative = {
         's3_uri': kwargs['s3_uri'],
         'asset_type': kwargs['asset_type'],
         'title': kwargs['title'],
         'description': kwargs['description'],
         'website_url': kwargs['website_url'],
     }
     self.set_parameter(self.create_carousel_slideshow_task_name,
                        'Social Carousel S3 URI {}'.format(n_creatives + 1), kwargs['s3_uri'])
     self.set_parameter(self.create_carousel_slideshow_task_name,
                        'Social S3 Type {}'.format(n_creatives + 1), kwargs['asset_type'])
     self.set_parameter(self.create_carousel_slideshow_task_name,
                        'Social Carousel Title {}'.format(n_creatives + 1), kwargs['title'])
     self.set_parameter(self.create_carousel_slideshow_task_name,
                        'Social Carousel Description {}'.format(n_creatives + 1), kwargs['description'])
     self.set_parameter(self.create_carousel_slideshow_task_name,
                        'Social Carousel URL {}'.format(n_creatives + 1), kwargs['website_url'])
     self._creatives.append(creative)
    def build(self):
        """
        @summary: build the Workfront project.
        @raise WFBrigeException
        @return: WFProject object
        """
        if not self.ad_groups:
            raise WFBrigeException(
                'The project does not have any Ad Groups. Please use add_ad_group to add them.'
            )

        project = WFProjectDisplayContainer(self.project_name)
        project.ttd_audience_id = self._ttd_audience_id
        project.ttd_campaign_id = self._ttd_campaign_id
        project.ttd_flight_id = self._ttd_flight_id
        project.ttd_creative_id = self._ttd_creative_id
        project.ttd_advertiser_id = self._ttd_advertiser_id
        project.is_targeted_bonus_media = self._is_targeted_bonus_media
        project.multiple_ad_groups = self._multiple_ad_groups
        project.project_type = self._project_type

        order_review_block = WFDisplayOrderReviewBlock()  # Manual

        data_block = WFDisplayDataBlock()
        data_block.audience_name = self._audience_name

        campaign_block = WFDisplayCampaignBlock()
        campaign_block.start_date_inclusive_utc = self._start_date_inclusive_utc
        campaign_block.end_date_exclusive_utc = self._end_date_exclusive_utc
        campaign_block.campaign_name = self._campaign_name
        campaign_block.campaign_overview = self._campaign_overview
        campaign_block.partner_cost_percentage_fee = self._partner_cost_percentage_fee
        campaign_block.availability = self._availability
        campaign_block.auto_allocator = self._auto_allocator
        campaign_block.ctv_targeting_and_attribution = self._ctv_targeting_and_attribution
        campaign_block.pacing_mode = self._pacing_mode
        campaign_block.partner_cpm_fee_amount = self._partner_cpm_fee_amount
        campaign_block.partner_cpm_fee_currency = self._partner_cpm_fee_currency
        campaign_block.partner_cpc_fee_amount = self._partner_cpc_fee_amount
        campaign_block.partner_cpc_fee_currency = self._partner_cpc_fee_currency
        campaign_block.max_bid_amount = self._max_bid_amount
        campaign_block.budget_in_impressions_pre_calc = self._budget_in_impressions_pre_calc
        campaign_block.daily_target_in_advertiser_currency = self._daily_target_in_advertiser_currency
        campaign_block.daily_target_in_impressions = self._daily_target_in_impressions

        ad_group_setup_blocks = []
        qa_blocks = []
        for ad_group in self.ad_groups:
            ad_group_setup_block = WFDisplayAdGroupSetupBlock()
            qa_block = WFDisplayQABlock()
            for creative in ad_group['creatives']:
                creative_upload_dict = {
                    k: creative[k]
                    for k in self.creative_upload_params if k in creative
                }
                ad_group_setup_block.add_creative(**creative_upload_dict)
                creative_qa_dict = {
                    k: creative[k]
                    for k in self.creative_qa_params if k in creative
                }
                qa_block.add_creative(**creative_qa_dict)
            ad_group_setup_block.add_ad_group(**ad_group)
            ad_group_setup_blocks.append(ad_group_setup_block)
            ad_group.update({
                'start_date_inclusive_utc':
                self._start_date_inclusive_utc,
                'end_date_exclusive_utc':
                self._end_date_exclusive_utc,
                'campaign_name':
                self._campaign_name,
                'campaign_overview':
                self._campaign_overview,
                'partner_cost_percentage_fee':
                self._partner_cost_percentage_fee,
                'availability':
                self._availability,
                'auto_allocator':
                self._auto_allocator,
                'ctv_targeting_and_attribution':
                self._ctv_targeting_and_attribution,
                'pacing_mode':
                self._pacing_mode,
                'partner_cpm_fee_amount':
                self._partner_cpm_fee_amount,
                'partner_cpm_fee_currency':
                self._partner_cpm_fee_currency,
                'partner_cpc_fee_amount':
                self._partner_cpc_fee_amount,
                'partner_cpc_fee_currency':
                self._partner_cpc_fee_currency,
                'max_bid_amount':
                self._max_bid_amount,
                'budget_in_impressions_pre_calc':
                self._budget_in_impressions_pre_calc,
                'daily_target_in_advertiser_currency':
                self._daily_target_in_advertiser_currency,
                'daily_target_in_impressions':
                self._daily_target_in_impressions,
            })
            qa_block.add_ad_group(**ad_group)
            qa_blocks.append(qa_block)

        launch_block = WFDisplayLaunchBlock()  # Manual

        project_blocks = [
            order_review_block,
            data_block,
            campaign_block,
        ]
        project_blocks.extend(ad_group_setup_blocks)
        project_blocks.extend(qa_blocks)
        project_blocks.append(launch_block)
        [project.append(block) for block in project_blocks]
        parser = WFBlockParser(self.wf)
        wf_project = parser.create(project)
        return wf_project
Пример #17
0
 def raise_missing(field_name):
     m = "{} is required for match and export data projects"
     raise WFBrigeException(m.format(field_name))
 def check_not_none(name, value):
     if value is None:
         raise WFBrigeException("{} is required".format(name))
Пример #19
0
 def _check_viability_b2c(self):
     if self.count_id is None:
         raise WFBrigeException("{} is required".format("count_id"))
    def add_ad_group(self, **kwargs):
        """
        Ad Group allowed kwargs:
        * ad_group_name
        * adg_base_bid_amount
        * ad_group_name
        * adg_base_bid_amount
        * adg_description
        * adg_daily_budget
        * adg_daily_budget_in_impressions
        * adg_budget_in_impressions_pre_calc
        * adg_pacing_mode
        * adg_auto_allocator_priority
        * adg_max_bid_amount
        * adg_frequency_period_in_minutes
        * adg_frequency_cap
        * adg_frequency_pricing_slope_cpm
        * adg_ctr_in_percent
        * device_type
        * country
        * category
        * ae_excluder
        * creatives

        Creative allowed kwargs:
        * creative_name - required
        * creative_size - required
        * image_s3_url - required
        * clickthrough_url - required
        * landing_page_url - required
        * third_party_tags
        * third_party_impression_tracking_url
        * third_party_impression_tracking_url2
        * third_party_impression_tracking_url3
        * securable
        * availability
        * third_party_tag
        * width
        * height
        * [Native Params]
        """
        allowed_kwargs = self.ad_group_params
        creative_kwargs = set(self.creative_upload_params +
                              self.creative_qa_params)
        ad_group = {}
        for k, v in kwargs.items():
            if k not in allowed_kwargs:
                raise WFBrigeException('Invalid Key {}'.format(k))
            elif k == 'creatives':
                ad_group['creatives'] = []
                for creative in v:
                    ad_group_creative = {}
                    for creative_key, creative_value in creative.items():
                        if creative_key not in creative_kwargs:
                            raise WFBrigeException(
                                'Invalid Key {}'.format(creative_key))
                        ad_group_creative[creative_key] = creative_value
                    ad_group['creatives'].append(ad_group_creative)
            else:
                ad_group[k] = v
        self.ad_groups.append(ad_group)