Example #1
0
class _BulkNegativeSiteIdentifier(_BulkEntityIdentifier):
    def __init__(self, status=None, entity_id=None, entity_name=None):
        self._status = status
        self._entity_id = entity_id
        self._entity_name = entity_name

    @property
    def status(self):
        return self._status

    @property
    def entity_id(self):
        return self._entity_id

    @property
    def entity_name(self):
        return self._entity_name

    @property
    def _parent_column_name(self):
        raise NotImplementedError()

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c._status),
            csv_to_field=lambda c, v: setattr(c, '_status', v if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: None
            if c._entity_id == 0 else bulk_str(c._entity_id),
            csv_to_field=lambda c, v: setattr(c, '_entity_id',
                                              int(v) if v else 0)),
        _DynamicColumnNameMapping(
            header_func=lambda c: c._parent_column_name,
            field_to_csv=lambda c: c._entity_name,
            csv_to_field=lambda c, v: setattr(c, '_entity_name', v))
    ]

    def __eq__(self, other):
        return type(self) == type(
            other) and self._entity_id == other._entity_id

    @property
    def is_delete_row(self):
        return self._status == 'Deleted'

    def read_from_row_values(self, row_values):
        row_values.convert_to_entity(self,
                                     _BulkNegativeSiteIdentifier._MAPPINGS)

    def write_to_row_values(self, row_values, exclude_readonly_data):
        self.convert_to_values(row_values,
                               _BulkNegativeSiteIdentifier._MAPPINGS)
 def _write_priority(c):
     if not c.campaign.CampaignType:
         return None
     if 'shopping' in [campaign_type.lower() for campaign_type in c.campaign.CampaignType]:
         shopping_setting = c._get_shopping_setting()
         if not shopping_setting:
             return None
         return bulk_str(shopping_setting.Priority)
 def _write_priority(c):
     if not c.campaign.CampaignType:
         return None
     if 'shopping' in [
             campaign_type.lower()
             for campaign_type in c.campaign.CampaignType
     ]:
         shopping_setting = c._get_shopping_setting()
         if not shopping_setting:
             return None
         return bulk_str(shopping_setting.Priority)
class BulkCampaignProductScope(_SingleRecordBulkEntity):
    """ Represents a Campaign Criterion that can be read or written in a bulk file.

    This class exposes the :attr:`campaign_criterion` property that can be read and written as fields of the
    Campaign Product Scope record in a bulk file.

    For more information, see Campaign Product Scope at http://go.microsoft.com/fwlink/?LinkId=618643.

    *See also:*

    * :class:`.BulkServiceManager`
    * :class:`.BulkOperation`
    * :class:`.BulkFileReader`
    * :class:`.BulkFileWriter`
    """
    def __init__(self,
                 campaign_name=None,
                 status=None,
                 campaign_criterion=None):
        super(BulkCampaignProductScope, self).__init__()

        self._campaign_name = campaign_name
        self._status = status
        self._campaign_criterion = campaign_criterion

    @classmethod
    def _add_product_condition_to_row_values(cls, entity, value):
        criterion = entity.campaign_criterion.Criterion
        if criterion is not None and hasattr(criterion, 'Conditions') and criterion.Conditions is not None and \
                hasattr(criterion.Conditions, 'ProductCondition'):
            return _ProductConditionHelper.add_row_values_from_conditions(
                criterion.Conditions.ProductCondition, value)
        return None

    _MAPPINGS = [
        _SimpleBulkMapping(header=_StringTable.Status,
                           field_to_csv=lambda c: c.status,
                           csv_to_field=lambda c, v: setattr(c, 'status', v)),
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c.campaign_criterion.Id),
            csv_to_field=lambda c, v: setattr(c.campaign_criterion, 'Id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(c.campaign_criterion.CampaignId),
            csv_to_field=lambda c, v: setattr(c.campaign_criterion,
                                              'CampaignId', int(v))),
        _SimpleBulkMapping(
            header=_StringTable.Campaign,
            field_to_csv=lambda c: c.campaign_name,
            csv_to_field=lambda c, v: setattr(c, 'campaign_name', v)),
        _ComplexBulkMapping(
            #entity_to_csv=lambda c, v: _ProductConditionHelper.add_row_values_from_conditions(
            #    c.campaign_criterion.Criterion.Conditions.ProductCondition,
            #    v
            #),
            entity_to_csv=lambda c, v: BulkCampaignProductScope.
            _add_product_condition_to_row_values(c, v),
            csv_to_entity=lambda v, c: _ProductConditionHelper.
            add_conditions_from_row_values(
                v, c.campaign_criterion.Criterion.Conditions.ProductCondition))
    ]

    @property
    def campaign_name(self):
        """ The name of the Campaign

        :rtype: str
        """

        return self._campaign_name

    @campaign_name.setter
    def campaign_name(self, campaign_name):
        self._campaign_name = campaign_name

    @property
    def status(self):
        """ The status of the Campaign Criterion

        :rtype: str
        """

        return self._status

    @status.setter
    def status(self, status):
        self._status = status

    @property
    def campaign_criterion(self):
        """ Defines a Campaign Criterion """

        return self._campaign_criterion

    @campaign_criterion.setter
    def campaign_criterion(self, campaign_criterion):
        self._campaign_criterion = campaign_criterion

    def process_mappings_from_row_values(self, row_values):
        self._campaign_criterion = _CAMPAIGN_OBJECT_FACTORY_V10.create(
            'CampaignCriterion')
        self._campaign_criterion.Type = 'CampaignCriterion'
        self._campaign_criterion.Criterion = _CAMPAIGN_OBJECT_FACTORY_V10.create(
            'ProductScope')
        self._campaign_criterion.Criterion.Type = 'ProductScope'

        row_values.convert_to_entity(self, BulkCampaignProductScope._MAPPINGS)

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self._validate_property_not_null(self.campaign_criterion,
                                         'campaign_criterion')
        self.convert_to_values(row_values, BulkCampaignProductScope._MAPPINGS)

    def read_additional_data(self, stream_reader):
        super(BulkCampaignProductScope,
              self).read_additional_data(stream_reader)
Example #5
0
class _BulkAdExtensionAssociation(_SingleRecordBulkEntity):
    """ This class provides properties that are shared by all bulk ad extension association classes.

    For more information, see Bulk File Schema at http://go.microsoft.com/fwlink/?LinkID=511639.
    """
    def __init__(self,
                 ad_extension_id_to_entity_id_association=None,
                 status=None,
                 editorial_status=None):
        super(_BulkAdExtensionAssociation, self).__init__()

        self._status = status
        self._ad_extension_id_to_entity_id_association = ad_extension_id_to_entity_id_association
        self._editorial_status = editorial_status
        self._performance_data = None

    @property
    def ad_extension_id_to_entity_id_association(self):
        """ Defines an association relationship between an ad extension and a supported entity, for example a campaign or ad group.

        :rtype: AdExtensionIdToEntityIdAssociation
        """

        return self._ad_extension_id_to_entity_id_association

    @ad_extension_id_to_entity_id_association.setter
    def ad_extension_id_to_entity_id_association(self, value):
        self._ad_extension_id_to_entity_id_association = value

    @property
    def status(self):
        """ The status of the ad extension association.

        The value is Active if the EntityId and AdExtensionId are associated. The value is Deleted if the association is removed.
        Corresponds to the 'Status' field in the bulk file.

        :rtype: str
        """

        return self._status

    @status.setter
    def status(self, status):
        self._status = status

    @property
    def editorial_status(self):
        """ The editorial status of the ad extension and associated entity.

        For more information, see AdExtensionEditorialStatus at http://go.microsoft.com/fwlink/?LinkId=511866.
        Corresponds to the 'Editorial Status' field in the bulk file.

        :rtype: str
        """

        return self._editorial_status

    @editorial_status.setter
    def editorial_status(self, editorial_status):
        self._editorial_status = editorial_status

    @property
    def performance_data(self):
        return self._performance_data

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(
                c.ad_extension_id_to_entity_id_association.AdExtensionId),
            csv_to_field=lambda c, v: setattr(
                c.ad_extension_id_to_entity_id_association, 'AdExtensionId',
                int(v))),
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c.status),
            csv_to_field=lambda c, v: setattr(c, '_status', v if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(
                c.ad_extension_id_to_entity_id_association.EntityId),
            csv_to_field=lambda c, v: setattr(
                c.ad_extension_id_to_entity_id_association, 'EntityId', int(v)
            )),
        _SimpleBulkMapping(
            header=_StringTable.EditorialStatus,
            field_to_csv=lambda c: c.editorial_status,
            csv_to_field=lambda c, v: setattr(c, '_editorial_status', v
                                              if v else None)),
    ]

    def process_mappings_from_row_values(self, row_values):
        self._ad_extension_id_to_entity_id_association = _CAMPAIGN_OBJECT_FACTORY.create(
            'AdExtensionIdToEntityIdAssociation')
        row_values.convert_to_entity(self,
                                     _BulkAdExtensionAssociation._MAPPINGS)
        self._performance_data = PerformanceData.read_from_row_values_or_null(
            row_values)

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self._validate_property_not_null(
            self._ad_extension_id_to_entity_id_association,
            'ad_extension_id_to_entity_id_association')
        self.convert_to_values(row_values,
                               _BulkAdExtensionAssociation._MAPPINGS)
        if not exclude_readonly_data:
            PerformanceData.write_to_row_values_if_not_null(
                self.performance_data, row_values)

    def read_additional_data(self, stream_reader):
        super(_BulkAdExtensionAssociation,
              self).read_additional_data(stream_reader)
Example #6
0
class _BulkAdExtensionIdentifier(_BulkEntityIdentifier):
    def __init__(self,
                 account_id=None,
                 ad_extension_id=None,
                 status=None,
                 version=None):
        super(_BulkAdExtensionIdentifier, self).__init__()

        self._account_id = account_id
        self._ad_extension_id = ad_extension_id
        self._status = status
        self._version = version

    @property
    def account_id(self):
        return self._account_id

    @account_id.setter
    def account_id(self, account_id):
        self._account_id = account_id

    @property
    def ad_extension_id(self):
        return self._ad_extension_id

    @ad_extension_id.setter
    def ad_extension_id(self, ad_extension_id):
        self._ad_extension_id = ad_extension_id

    @property
    def status(self):
        return self._status

    @status.setter
    def status(self, status):
        self._status = status

    @property
    def version(self):
        return self._version

    @version.setter
    def version(self, version):
        self._version = version

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c.status),
            csv_to_field=lambda c, v: setattr(c, 'status', v if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c.ad_extension_id),
            csv_to_field=lambda c, v: setattr(c, 'ad_extension_id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Version,
            field_to_csv=lambda c: bulk_str(c.version),
            csv_to_field=lambda c, v: setattr(c, 'version',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(c.account_id),
            csv_to_field=lambda c, v: setattr(c, 'account_id', int(v))),
    ]

    def read_from_row_values(self, row_values):
        row_values.convert_to_entity(self,
                                     _BulkAdExtensionIdentifier._MAPPINGS)

    def write_to_row_values(self, row_values, exclude_readonly_data):
        self.convert_to_values(row_values,
                               _BulkAdExtensionIdentifier._MAPPINGS)

    def __eq__(self, other):
        raise NotImplementedError()

    @property
    def is_delete_row(self):
        return self._status == 'Deleted'
Example #7
0
class _BulkAdExtensionBase(_SingleRecordBulkEntity):
    """ This class provides properties that are shared by all bulk ad extension classes.

    *See also:*

    * :class:`.BulkCallAdExtension`
    * :class:`.BulkImageAdExtension`
    * :class:`.BulkLocationAdExtension`
    * :class:`.BulkProductAdExtension`
    * :class:`.BulkSiteLinkAdExtension`
    """
    def __init__(self, account_id=None, ad_extension=None):
        super(_BulkAdExtensionBase, self).__init__()

        self._account_id = account_id
        self._ad_extension = ad_extension

    @property
    def account_id(self):
        """ The ad extension's parent account identifier.

        Corresponds to the 'Parent Id' field in the bulk file.

        :rtype: int
        """

        return self._account_id

    @account_id.setter
    def account_id(self, account_id):
        self._account_id = account_id

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c._ad_extension.Status),
            csv_to_field=lambda c, v: setattr(c._ad_extension, 'Status', v
                                              if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c._ad_extension.Id),
            csv_to_field=lambda c, v: setattr(c._ad_extension, 'Id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Version,
            field_to_csv=lambda c: bulk_str(c._ad_extension.Version),
            csv_to_field=lambda c, v: setattr(c._ad_extension, 'Version',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(c.account_id),
            csv_to_field=lambda c, v: setattr(c, 'account_id', int(v))),
    ]

    def process_mappings_from_row_values(self, row_values):
        row_values.convert_to_entity(self, _BulkAdExtensionBase._MAPPINGS)

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self.convert_to_values(row_values, _BulkAdExtensionBase._MAPPINGS)

    def read_additional_data(self, stream_reader):
        super(_BulkAdExtensionBase, self).read_additional_data(stream_reader)
class BulkCampaign(_SingleRecordBulkEntity):
    """ Represents a campaign that can be read or written in a bulk file.

    This class exposes the :attr:`campaign` property that can be read and written as fields of the
    Campaign record in a bulk file.

    For more information, see Campaign at http://go.microsoft.com/fwlink/?LinkID=511521.

    *See also:*

    * :class:`.BulkServiceManager`
    * :class:`.BulkOperation`
    * :class:`.BulkFileReader`
    * :class:`.BulkFileWriter`
    """
    def __init__(self, account_id=None, campaign=None):
        super(BulkCampaign, self).__init__()

        self._account_id = account_id
        self._campaign = campaign
        self._quality_score_data = None
        self._performance_data = None

    @property
    def account_id(self):
        """ The identifier of the account that contains the campaign.

        Corresponds to the 'Parent Id' field in the bulk file.

        :rtype: int
        """

        return self._account_id

    @account_id.setter
    def account_id(self, account_id):
        self._account_id = account_id

    @property
    def campaign(self):
        """ Defines a campaign within an account.

        See Campaign at https://msdn.microsoft.com/en-us/library/bing-ads-campaign-management-campaign.aspx
        """

        return self._campaign

    @campaign.setter
    def campaign(self, campaign):
        self._campaign = campaign

    @property
    def quality_score_data(self):
        """ The quality score data for the campaign.

        :rtype: QualityScoreData
        """

        return self._quality_score_data

    @property
    def performance_data(self):
        """ The historical performance data for the campaign

        :rtype: PerformanceData
        """

        return self._performance_data

    def _get_shopping_setting(self):
        if not self.campaign.Settings.Setting:
            return None
        shopping_settings = [
            setting for setting in self.campaign.Settings.Setting
            if isinstance(setting, _ShoppingSetting)
        ]
        if len(shopping_settings) != 1:
            raise ValueError(
                'Can only have 1 ShoppingSetting in Campaign Settings.')
        return shopping_settings[0]

    @staticmethod
    def _write_campaign_type(c):
        if not c.campaign.CampaignType:
            return None
        if len(c.campaign.CampaignType) != 1:
            raise ValueError("Only 1 CampaignType can be set in Campaign")
        return c.campaign.CampaignType[0]

    @staticmethod
    def _read_campaign_type(c, v):
        if not v:
            return []
        campaign_type = v
        c.campaign.CampaignType = [campaign_type]
        if campaign_type.lower() == 'shopping':
            c.campaign.Settings = _CAMPAIGN_OBJECT_FACTORY.create(
                'ArrayOfSetting')
            shopping_setting = _CAMPAIGN_OBJECT_FACTORY.create(
                'ShoppingSetting')
            shopping_setting.Type = 'ShoppingSetting'
            c.campaign.Settings.Setting = [shopping_setting]

    @staticmethod
    def _write_store_id(c):
        if not c.campaign.CampaignType:
            return None
        if 'shopping' in [
                campaign_type.lower()
                for campaign_type in c.campaign.CampaignType
        ]:
            shopping_setting = c._get_shopping_setting()
            if not shopping_setting:
                return None
            return bulk_str(shopping_setting.StoreId)

    @staticmethod
    def _read_store_id(c, v):
        if not c.campaign.CampaignType:
            return None
        if 'shopping' in [
                campaign_type.lower()
                for campaign_type in c.campaign.CampaignType
        ]:
            shopping_setting = c._get_shopping_setting()
            if not shopping_setting:
                return None
            shopping_setting.StoreId = int(v) if v else None

    @staticmethod
    def _write_priority(c):
        if not c.campaign.CampaignType:
            return None
        if 'shopping' in [
                campaign_type.lower()
                for campaign_type in c.campaign.CampaignType
        ]:
            shopping_setting = c._get_shopping_setting()
            if not shopping_setting:
                return None
            return bulk_str(shopping_setting.Priority)

    @staticmethod
    def _read_priority(c, v):
        if not c.campaign.CampaignType:
            return None
        if 'shopping' in [
                campaign_type.lower()
                for campaign_type in c.campaign.CampaignType
        ]:
            shopping_setting = c._get_shopping_setting()
            if not shopping_setting:
                return None
            shopping_setting.Priority = int(v) if v else None

    @staticmethod
    def _write_sales_country_code(c):
        if not c.campaign.CampaignType:
            return None
        if 'shopping' in [
                campaign_type.lower()
                for campaign_type in c.campaign.CampaignType
        ]:
            shopping_setting = c._get_shopping_setting()
            if not shopping_setting:
                return None
            return shopping_setting.SalesCountryCode

    @staticmethod
    def _read_sales_country_code(c, v):
        if not c.campaign.CampaignType:
            return None
        if 'shopping' in [
                campaign_type.lower()
                for campaign_type in c.campaign.CampaignType
        ]:
            shopping_setting = c._get_shopping_setting()
            if not shopping_setting:
                return None
            shopping_setting.SalesCountryCode = v

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.CampaignType,
            field_to_csv=lambda c: BulkCampaign._write_campaign_type(c),
            csv_to_field=lambda c, v: BulkCampaign._read_campaign_type(c, v)),
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c.campaign.Status),
            csv_to_field=lambda c, v: setattr(c.campaign, 'Status', v
                                              if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c.campaign.Id),
            csv_to_field=lambda c, v: setattr(c.campaign, 'Id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(c.account_id),
            csv_to_field=lambda c, v: setattr(c, '_account_id', int(v))),
        _SimpleBulkMapping(
            header=_StringTable.Campaign,
            field_to_csv=lambda c: c.campaign.Name,
            csv_to_field=lambda c, v: setattr(c.campaign, 'Name', v)),
        _SimpleBulkMapping(
            header=_StringTable.TimeZone,
            field_to_csv=lambda c: c.campaign.TimeZone,
            csv_to_field=lambda c, v: setattr(c.campaign, 'TimeZone', v)),
        _SimpleBulkMapping(
            header=_StringTable.BudgetType,
            field_to_csv=lambda c: bulk_str(c.campaign.BudgetType),
            csv_to_field=lambda c, v: setattr(c.campaign, 'BudgetType', v
                                              if v else None)),
        _ComplexBulkMapping(budget_to_csv, csv_to_budget),
        _SimpleBulkMapping(
            header=_StringTable.BidAdjustment,
            field_to_csv=lambda c: bulk_str(c.campaign.NativeBidAdjustment),
            csv_to_field=lambda c, v: setattr(c.campaign,
                                              'NativeBidAdjustment',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.BingMerchantCenterId,
            field_to_csv=lambda c: BulkCampaign._write_store_id(c),
            csv_to_field=lambda c, v: BulkCampaign._read_store_id(c, v)),
        _SimpleBulkMapping(
            header=_StringTable.CampaignPriority,
            field_to_csv=lambda c: BulkCampaign._write_priority(c),
            csv_to_field=lambda c, v: BulkCampaign._read_priority(c, v)),
        _SimpleBulkMapping(
            header=_StringTable.CountryCode,
            field_to_csv=lambda c: BulkCampaign._write_sales_country_code(c),
            csv_to_field=lambda c, v: BulkCampaign._read_sales_country_code(
                c, v))
    ]

    def read_additional_data(self, stream_reader):
        super(BulkCampaign, self).read_additional_data(stream_reader)

    def process_mappings_from_row_values(self, row_values):
        self._campaign = _CAMPAIGN_OBJECT_FACTORY.create('Campaign')
        row_values.convert_to_entity(self, BulkCampaign._MAPPINGS)
        self._quality_score_data = QualityScoreData.read_from_row_values_or_null(
            row_values)
        self._performance_data = PerformanceData.read_from_row_values_or_null(
            row_values)

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self._validate_property_not_null(self.campaign, 'campaign')
        self.convert_to_values(row_values, BulkCampaign._MAPPINGS)
        if not exclude_readonly_data:
            QualityScoreData.write_to_row_values_if_not_null(
                self.quality_score_data, row_values)
            PerformanceData.write_to_row_values_if_not_null(
                self.performance_data, row_values)
 def _get_parent_criterion_id(cls, entity):
     if entity.ad_group_criterion.Criterion is not None and \
             hasattr(entity.ad_group_criterion.Criterion, 'ParentCriterionId'):
         return bulk_str(entity.ad_group_criterion.Criterion.ParentCriterionId)
     return None
Example #10
0
class BulkCampaign(_SingleRecordBulkEntity):
    """ Represents a campaign that can be read or written in a bulk file.

    This class exposes the :attr:`campaign` property that can be read and written as fields of the
    Campaign record in a bulk file.

    For more information, see Campaign at http://go.microsoft.com/fwlink/?LinkID=511521.

    *See also:*

    * :class:`.BulkServiceManager`
    * :class:`.BulkOperation`
    * :class:`.BulkFileReader`
    * :class:`.BulkFileWriter`
    """
    def __init__(self, account_id=None, campaign=None):
        super(BulkCampaign, self).__init__()

        self._account_id = account_id
        self._campaign = campaign
        self._quality_score_data = None
        self._performance_data = None

    @property
    def account_id(self):
        """ The identifier of the account that contains the campaign.

        Corresponds to the 'Parent Id' field in the bulk file.

        :rtype: int
        """

        return self._account_id

    @account_id.setter
    def account_id(self, account_id):
        self._account_id = account_id

    @property
    def campaign(self):
        """ Defines a campaign within an account.

        See Campaign at https://msdn.microsoft.com/en-us/library/bing-ads-campaign-management-campaign.aspx
        """

        return self._campaign

    @campaign.setter
    def campaign(self, campaign):
        self._campaign = campaign

    @property
    def quality_score_data(self):
        """ The quality score data for the campaign.

        :rtype: QualityScoreData
        """

        return self._quality_score_data

    @property
    def performance_data(self):
        """ The historical performance data for the campaign

        :rtype: PerformanceData
        """

        return self._performance_data

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c.campaign.Status),
            csv_to_field=lambda c, v: setattr(c.campaign, 'Status', v
                                              if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c.campaign.Id),
            csv_to_field=lambda c, v: setattr(c.campaign, 'Id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(c.account_id),
            csv_to_field=lambda c, v: setattr(c, '_account_id', int(v))),
        _SimpleBulkMapping(
            header=_StringTable.Campaign,
            field_to_csv=lambda c: c.campaign.Name,
            csv_to_field=lambda c, v: setattr(c.campaign, 'Name', v)),
        _SimpleBulkMapping(
            header=_StringTable.TimeZone,
            field_to_csv=lambda c: c.campaign.TimeZone,
            csv_to_field=lambda c, v: setattr(c.campaign, 'TimeZone', v)),
        _SimpleBulkMapping(
            header=_StringTable.BudgetType,
            field_to_csv=lambda c: bulk_str(c.campaign.BudgetType),
            csv_to_field=lambda c, v: setattr(c.campaign, 'BudgetType', v
                                              if v else None)),
        _ComplexBulkMapping(budget_to_csv, csv_to_budget)
    ]

    def read_additional_data(self, stream_reader):
        super(BulkCampaign, self).read_additional_data(stream_reader)

    def process_mappings_from_row_values(self, row_values):
        self._campaign = _CAMPAIGN_OBJECT_FACTORY.create('Campaign')
        row_values.convert_to_entity(self, BulkCampaign._MAPPINGS)
        self._quality_score_data = QualityScoreData.read_from_row_values_or_null(
            row_values)
        self._performance_data = PerformanceData.read_from_row_values_or_null(
            row_values)

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self._validate_property_not_null(self.campaign, 'campaign')
        self.convert_to_values(row_values, BulkCampaign._MAPPINGS)
        if not exclude_readonly_data:
            QualityScoreData.write_to_row_values_if_not_null(
                self.quality_score_data, row_values)
            PerformanceData.write_to_row_values_if_not_null(
                self.performance_data, row_values)
class _BulkNegativeKeyword(_SingleRecordBulkEntity):
    """ The base class for all bulk negative keywords.

    Either assigned individually to a campaign or ad group entity, or shared in a negative keyword list.

    *See also:*

    * :class:`.BulkAdGroupNegativeKeyword`
    * :class:`.BulkCampaignNegativeKeyword`
    * :class:`.BulkSharedNegativeKeyword`
    """
    def __init__(self, status=None, negative_keyword=None, parent_id=None):
        super(_BulkNegativeKeyword, self).__init__()

        self._negative_keyword = negative_keyword
        self._status = status
        self._parent_id = parent_id

    @property
    def status(self):
        """ The status of the negative keyword association.

        The value is 'Active' if the negative keyword is assigned to the parent entity.
        The value is 'Deleted' if the negative keyword is removed from the parent entity,
                                    or should be removed in a subsequent upload operation.
        :rtype: str
        """
        return self._status

    @status.setter
    def status(self, status):
        self._status = status

    @property
    def negative_keyword(self):
        """ Defines a negative keyword with match type. """

        return self._negative_keyword

    @negative_keyword.setter
    def negative_keyword(self, negative_keyword):
        self._negative_keyword = negative_keyword

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c.negative_keyword.Id),
            csv_to_field=lambda c, v: setattr(c.negative_keyword, 'Id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c.status),
            csv_to_field=lambda c, v: setattr(c, '_status', v if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(c._parent_id),
            csv_to_field=lambda c, v: setattr(c, '_parent_id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Keyword,
            field_to_csv=lambda c: c.negative_keyword.Text,
            csv_to_field=lambda c, v: setattr(c.negative_keyword, 'Text', v)),
        _SimpleBulkMapping(
            header=_StringTable.MatchType,
            field_to_csv=lambda c: bulk_str(c.negative_keyword.MatchType),
            csv_to_field=lambda c, v: setattr(c.negative_keyword, 'MatchType',
                                              v))
    ]

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self._validate_property_not_null(self._negative_keyword,
                                         'negative_keyword')
        self.convert_to_values(row_values, _BulkNegativeKeyword._MAPPINGS)

    def process_mappings_from_row_values(self, row_values):
        self._negative_keyword = _CAMPAIGN_OBJECT_FACTORY.create(
            'NegativeKeyword')
        self._negative_keyword.Type = 'NegativeKeyword'
        row_values.convert_to_entity(self, _BulkNegativeKeyword._MAPPINGS)

    def read_additional_data(self, stream_reader):
        super(_BulkNegativeKeyword, self).read_additional_data(stream_reader)
class BulkNegativeKeywordList(_SingleRecordBulkEntity):
    """ Represents a negative keyword list that can be read or written in a bulk file.

    This class exposes the :attr:`.BulkNegativeKeywordList.negative_keyword_list` property that can be read and
    written as fields of the Negative Keyword List record in a bulk file.

    For more information, see Negative Keyword List at http://go.microsoft.com/fwlink/?LinkID=511519.

    *See also:*

    * :class:`.BulkServiceManager`
    * :class:`.BulkOperation`
    * :class:`.BulkFileReader`
    * :class:`.BulkFileWriter`
    """
    def __init__(self, status=None, negative_keyword_list=None):
        super(BulkNegativeKeywordList, self).__init__()

        self._status = status
        self._negative_keyword_list = negative_keyword_list

    @property
    def negative_keyword_list(self):
        """ The negative keyword list.

        see Negative Keyword List at http://go.microsoft.com/fwlink/?LinkID=511519.
        """

        return self._negative_keyword_list

    @negative_keyword_list.setter
    def negative_keyword_list(self, negative_keyword_list):
        self._negative_keyword_list = negative_keyword_list

    @property
    def status(self):
        """ The status of the negative keyword list.

        :rtype: str
        """

        return self._status

    @status.setter
    def status(self, status):
        self._status = status

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c.negative_keyword_list.Id),
            csv_to_field=lambda c, v: setattr(c.negative_keyword_list, 'Id',
                                              int(v) if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: bulk_str(c.status),
            csv_to_field=lambda c, v: setattr(c, 'status', v if v else None)),
        _SimpleBulkMapping(header=_StringTable.Name,
                           field_to_csv=lambda c: c.negative_keyword_list.Name,
                           csv_to_field=lambda c, v: setattr(
                               c.negative_keyword_list, 'Name', v))
    ]

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self._validate_property_not_null(self._negative_keyword_list,
                                         'negative_keyword_list')
        self.convert_to_values(row_values, BulkNegativeKeywordList._MAPPINGS)

    def process_mappings_from_row_values(self, row_values):
        self._negative_keyword_list = _CAMPAIGN_OBJECT_FACTORY.create(
            'NegativeKeywordList')
        self._negative_keyword_list.Type = 'NegativeKeywordList'
        row_values.convert_to_entity(self, BulkNegativeKeywordList._MAPPINGS)

    def read_additional_data(self, stream_reader):
        super(BulkNegativeKeywordList,
              self).read_additional_data(stream_reader)
class BulkCampaignNegativeKeywordList(_SingleRecordBulkEntity):
    """ Represents a negative keyword list that is assigned to a campaign. Each negative keyword list can be read or written in a bulk file.

    This class exposes the :attr:`BulkCampaignNegativeKeywordList.SharedEntityAssociation` property that can be read
    and written as fields of the Campaign Negative Keyword List Association record in a bulk file.

    For more information, see Campaign Negative Keyword List Association at http://go.microsoft.com/fwlink/?LinkID=511523.

    *See also:*

    * :class:`.BulkServiceManager`
    * :class:`.BulkOperation`
    * :class:`.BulkFileReader`
    * :class:`.BulkFileWriter`
    """
    def __init__(self, status=None, shared_entity_association=None):
        super(BulkCampaignNegativeKeywordList, self).__init__()

        self._shared_entity_association = shared_entity_association
        self._status = status

    @property
    def status(self):
        """ The status of the negative keyword list association.

        :rtype: str
        """

        return self._status

    @status.setter
    def status(self, status):
        self._status = status

    @property
    def shared_entity_association(self):
        """ The campaign and negative keyword list identifiers.

        see Campaign Negative Keyword List Association at http://go.microsoft.com/fwlink/?LinkID=511523.
        """

        return self._shared_entity_association

    @shared_entity_association.setter
    def shared_entity_association(self, shared_entity_association):
        self._shared_entity_association = shared_entity_association

    _MAPPINGS = [
        _SimpleBulkMapping(
            header=_StringTable.Status,
            field_to_csv=lambda c: c.status,
            csv_to_field=lambda c, v: setattr(c, 'status', v if v else None)),
        _SimpleBulkMapping(
            header=_StringTable.Id,
            field_to_csv=lambda c: bulk_str(c.shared_entity_association.
                                            SharedEntityId),
            csv_to_field=lambda c, v: setattr(c.shared_entity_association,
                                              'SharedEntityId', int(v))),
        _SimpleBulkMapping(
            header=_StringTable.ParentId,
            field_to_csv=lambda c: bulk_str(c.shared_entity_association.
                                            EntityId),
            csv_to_field=lambda c, v: setattr(c.shared_entity_association,
                                              'EntityId', int(v))),
    ]

    def process_mappings_to_row_values(self, row_values,
                                       exclude_readonly_data):
        self._validate_property_not_null(self._shared_entity_association,
                                         'shared_entity_association')
        self.convert_to_values(row_values,
                               BulkCampaignNegativeKeywordList._MAPPINGS)

    def process_mappings_from_row_values(self, row_values):
        self._shared_entity_association = _CAMPAIGN_OBJECT_FACTORY.create(
            'SharedEntityAssociation')
        self._shared_entity_association.EntityType = 'Campaign'
        self._shared_entity_association.SharedEntityType = 'NegativeKeywordList'
        row_values.convert_to_entity(self,
                                     BulkCampaignNegativeKeywordList._MAPPINGS)

    def read_additional_data(self, stream_reader):
        super(BulkCampaignNegativeKeywordList,
              self).read_additional_data(stream_reader)