diff --git a/HISTORY.rst b/HISTORY.rst index 4ef661aa..c93960ac 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,14 @@ .. :changelog: Release History +13.0.7(2020-12-16) ++++++++++++++++++++++++++ + +* Update Bing Ads API Version 13 service proxies to reflect recent interface changes. For details please see the Bing Ads API Release Notes: https://docs.microsoft.com/en-us/bingads/guides/release-notes. +* Add bulk mappings for flyer ad extensions i.e., BulkFlyerAdExtension, BulkAccountFlyerAdExtension, BulkAdGroupFlyerAdExtension, and BulkCampaignFlyerAdExtension. +* Add ImpressionTrackingUrls mapping in the BulkResponsiveAd. +* Update the pattern matching to resolve EntityReadException with BulkCombinedList download. + 13.0.6(2020-10-14) +++++++++++++++++++++++++ diff --git a/bingads/authorization.py b/bingads/authorization.py index ad08a678..cbaf6b02 100644 --- a/bingads/authorization.py +++ b/bingads/authorization.py @@ -689,6 +689,9 @@ def get_access_token(**kwargs): if 'client_secret' in kwargs and kwargs['client_secret'] is None: del kwargs['client_secret'] + if 'requireliveconnect' in kwargs and kwargs['requireliveconnect'] == True: + del kwargs['tenant'] + auth_token_url = _UriOAuthService.AUTH_TOKEN_URI[(kwargs['environment'], kwargs['requireliveconnect'])] if 'tenant' in kwargs and kwargs['tenant'] is not None: diff --git a/bingads/manifest.py b/bingads/manifest.py index c7d92fd0..6d4e593a 100644 --- a/bingads/manifest.py +++ b/bingads/manifest.py @@ -1,5 +1,5 @@ import sys -VERSION = '13.0.6' +VERSION = '13.0.7' BULK_FORMAT_VERSION_6 = '6.0' WORKING_NAME = 'BingAdsSDKPython' USER_AGENT = '{0} {1} {2}'.format(WORKING_NAME, VERSION, sys.version_info[0:3]) diff --git a/bingads/v13/bulk/entities/ad_extensions/__init__.py b/bingads/v13/bulk/entities/ad_extensions/__init__.py index eed24cb0..a296f4ca 100644 --- a/bingads/v13/bulk/entities/ad_extensions/__init__.py +++ b/bingads/v13/bulk/entities/ad_extensions/__init__.py @@ -11,4 +11,5 @@ from .bulk_price_ad_extensions import * from .bulk_action_ad_extensions import * from .bulk_promotion_ad_extensions import * -from .bulk_filterlink_ad_extensions import * \ No newline at end of file +from .bulk_filterlink_ad_extensions import * +from .bulk_flyer_ad_extensions import * \ No newline at end of file diff --git a/bingads/v13/bulk/entities/ad_extensions/bulk_flyer_ad_extensions.py b/bingads/v13/bulk/entities/ad_extensions/bulk_flyer_ad_extensions.py new file mode 100644 index 00000000..28a95189 --- /dev/null +++ b/bingads/v13/bulk/entities/ad_extensions/bulk_flyer_ad_extensions.py @@ -0,0 +1,171 @@ +from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping +from bingads.v13.internal.bulk.string_table import _StringTable +from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13 + +from bingads.v13.internal.extensions import * +from .common import _BulkAdExtensionBase +from .common import _BulkCampaignAdExtensionAssociation +from .common import _BulkAdGroupAdExtensionAssociation +from .common import _BulkAccountAdExtensionAssociation + +_FlyerAdExtension = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('FlyerAdExtension')) + + +class BulkFlyerAdExtension(_BulkAdExtensionBase): + """ Represents a flyer ad extension. + + This class exposes the :attr:`flyer_ad_extension` property that can be read and written + as fields of the Flyer Ad Extension record in a bulk file. + + For more information, see Flyer Ad Extension at https://go.microsoft.com/fwlink/?linkid=846127. + + *See also:* + + * :class:`.BulkServiceManager` + * :class:`.BulkOperation` + * :class:`.BulkFileReader` + * :class:`.BulkFileWriter` + """ + + def __init__(self, account_id=None, ad_extension=None): + if ad_extension and not isinstance(ad_extension, _FlyerAdExtension): + raise ValueError('The type of ad_extension is: {0}, should be: {1}'.format( + type(ad_extension), + 'FlyerAdExtension' + )) + super(BulkFlyerAdExtension, self).__init__( + account_id=account_id, + ad_extension=ad_extension + ) + + @property + def flyer_ad_extension(self): + """ The flyer ad extension. + + see Flyer Ad Extension at https://go.microsoft.com/fwlink/?linkid=846127. + """ + + return self._ad_extension + + @flyer_ad_extension.setter + def flyer_ad_extension(self, value): + self._ad_extension = value + + _MAPPINGS = [ + _SimpleBulkMapping( + header=_StringTable.FlyerName, + field_to_csv=lambda c: bulk_str(c.flyer_ad_extension.FlyerName), + csv_to_field=lambda c, v: setattr(c.flyer_ad_extension, 'FlyerName', v) + ), + _SimpleBulkMapping( + header=_StringTable.MerchantCenterId, + field_to_csv=lambda c: bulk_str(c.flyer_ad_extension.StoreId), + csv_to_field=lambda c, v: setattr(c.flyer_ad_extension, 'StoreId', int(v) if v else None) + ), + _SimpleBulkMapping( + header=_StringTable.Description, + field_to_csv=lambda c: bulk_str(c.flyer_ad_extension.Description), + csv_to_field=lambda c, v: setattr(c.flyer_ad_extension, 'Description', v) + ), + _SimpleBulkMapping( + header=_StringTable.MediaIds, + field_to_csv=lambda c: field_to_csv_MediaIds(c.flyer_ad_extension), + csv_to_field=lambda c, v: csv_to_field_MediaIds(c.flyer_ad_extension, v) + ), + _SimpleBulkMapping( + header=_StringTable.FinalUrlSuffix, + field_to_csv=lambda c: bulk_optional_str(c.flyer_ad_extension.FinalUrlSuffix, c.flyer_ad_extension.Id), + csv_to_field=lambda c, v: setattr(c.flyer_ad_extension, 'FinalUrlSuffix', v) + ), + _SimpleBulkMapping( + header=_StringTable.TrackingTemplate, + field_to_csv=lambda c: bulk_str(c.flyer_ad_extension.TrackingUrlTemplate), + csv_to_field=lambda c, v: setattr(c.flyer_ad_extension, 'TrackingUrlTemplate', v if v else None) + ), + _SimpleBulkMapping( + header=_StringTable.CustomParameter, + field_to_csv=lambda c: field_to_csv_UrlCustomParameters(c.flyer_ad_extension), + csv_to_field=lambda c, v: csv_to_field_UrlCustomParameters(c.flyer_ad_extension, v) + ), + _SimpleBulkMapping( + header=_StringTable.FinalUrl, + field_to_csv=lambda c: field_to_csv_Urls(c.flyer_ad_extension.FinalUrls, c.flyer_ad_extension.Id), + csv_to_field=lambda c, v: csv_to_field_Urls(c.flyer_ad_extension.FinalUrls, v) + ), + _SimpleBulkMapping( + header=_StringTable.FinalMobileUrl, + field_to_csv=lambda c: field_to_csv_Urls(c.flyer_ad_extension.FinalMobileUrls, c.flyer_ad_extension.Id), + csv_to_field=lambda c, v: csv_to_field_Urls(c.flyer_ad_extension.FinalMobileUrls, v) + ), + _SimpleBulkMapping( + header=_StringTable.MediaUrls, + field_to_csv=lambda c: field_to_csv_Urls(c.flyer_ad_extension.ImageMediaUrls, c.flyer_ad_extension.Id), + csv_to_field=lambda c, v: csv_to_field_Urls(c.flyer_ad_extension.ImageMediaUrls, v) + ), + ] + + def process_mappings_from_row_values(self, row_values): + self.flyer_ad_extension = _CAMPAIGN_OBJECT_FACTORY_V13.create('FlyerAdExtension') + self.flyer_ad_extension.Type = 'FlyerAdExtension' + super(BulkFlyerAdExtension, self).process_mappings_from_row_values(row_values) + row_values.convert_to_entity(self, BulkFlyerAdExtension._MAPPINGS) + + def process_mappings_to_row_values(self, row_values, exclude_readonly_data): + self._validate_property_not_null(self.flyer_ad_extension, 'flyer_ad_extension') + super(BulkFlyerAdExtension, self).process_mappings_to_row_values(row_values, exclude_readonly_data) + self.convert_to_values(row_values, BulkFlyerAdExtension._MAPPINGS) + + +class BulkAccountFlyerAdExtension(_BulkAccountAdExtensionAssociation): + """ Represents an account level flyer ad extension. + + This class exposes properties that can be read and written + as fields of the Account Flyer Ad Extension record in a bulk file. + + For more information, see Account Flyer Ad Extension at https://go.microsoft.com/fwlink/?linkid=846127. + + *See also:* + + * :class:`.BulkServiceManager` + * :class:`.BulkOperation` + * :class:`.BulkFileReader` + * :class:`.BulkFileWriter` + """ + + pass + + +class BulkCampaignFlyerAdExtension(_BulkCampaignAdExtensionAssociation): + """ Represents a campaign level imflyerage ad extension. + + This class exposes properties that can be read and written + as fields of the Campaign Flyer Ad Extension record in a bulk file. + + For more information, see Campaign Flyer Ad Extension at https://go.microsoft.com/fwlink/?linkid=846127. + + *See also:* + + * :class:`.BulkServiceManager` + * :class:`.BulkOperation` + * :class:`.BulkFileReader` + """ + + pass + +class BulkAdGroupFlyerAdExtension(_BulkAdGroupAdExtensionAssociation): + """ Represents an ad group level flyer ad extension. + + This class exposes properties that can be read and written + as fields of the Ad Group Flyer Ad Extension record in a bulk file. + + For more information, see Ad Group Flyer Ad Extension at https://go.microsoft.com/fwlink/?linkid=846127. + + *See also:* + + * :class:`.BulkServiceManager` + * :class:`.BulkOperation` + * :class:`.BulkFileReader` + * :class:`.BulkFileWriter` + """ + + pass diff --git a/bingads/v13/bulk/entities/bulk_ads.py b/bingads/v13/bulk/entities/bulk_ads.py index 5739d3d8..895943f5 100644 --- a/bingads/v13/bulk/entities/bulk_ads.py +++ b/bingads/v13/bulk/entities/bulk_ads.py @@ -636,26 +636,6 @@ def responsive_ad(self, responsive_ad): field_to_csv=lambda c: c.responsive_ad.LongHeadlineString, csv_to_field=lambda c, v: setattr(c.responsive_ad, 'LongHeadlineString', v) ), - _SimpleBulkMapping( - header=_StringTable.LandscapeImageMediaId, - field_to_csv=lambda c: c.responsive_ad.LandscapeImageMediaId, - csv_to_field=lambda c, v: setattr(c.responsive_ad, 'LandscapeImageMediaId', int(v) if v else None) - ), - _SimpleBulkMapping( - header=_StringTable.LandscapeLogoMediaId, - field_to_csv=lambda c: c.responsive_ad.LandscapeLogoMediaId, - csv_to_field=lambda c, v: setattr(c.responsive_ad, 'LandscapeLogoMediaId', int(v) if v else None) - ), - _SimpleBulkMapping( - header=_StringTable.SquareImageMediaId, - field_to_csv=lambda c: c.responsive_ad.SquareImageMediaId, - csv_to_field=lambda c, v: setattr(c.responsive_ad, 'SquareImageMediaId', int(v) if v else None) - ), - _SimpleBulkMapping( - header=_StringTable.SquareLogoMediaId, - field_to_csv=lambda c: c.responsive_ad.SquareLogoMediaId, - csv_to_field=lambda c, v: setattr(c.responsive_ad, 'SquareLogoMediaId', int(v) if v else None) - ), _SimpleBulkMapping( header=_StringTable.Text, field_to_csv=lambda c: c.responsive_ad.Text, @@ -666,6 +646,11 @@ def responsive_ad(self, responsive_ad): field_to_csv=lambda c: field_to_csv_ImageAssetLinks(c.responsive_ad.Images), csv_to_field=lambda c, v: csv_to_field_ImageAssetLinks(c.responsive_ad.Images, v) ), + _SimpleBulkMapping( + header=_StringTable.ImpressionTrackingUrls, + field_to_csv=lambda c: field_to_csv_Urls(c.responsive_ad.ImpressionTrackingUrls, c.ad.Id), + csv_to_field=lambda c, v: csv_to_field_Urls(c.responsive_ad.ImpressionTrackingUrls, v) + ) ] def process_mappings_from_row_values(self, row_values): diff --git a/bingads/v13/bulk/entities/bulk_campaign.py b/bingads/v13/bulk/entities/bulk_campaign.py index 3d55f119..77f7c61d 100644 --- a/bingads/v13/bulk/entities/bulk_campaign.py +++ b/bingads/v13/bulk/entities/bulk_campaign.py @@ -361,7 +361,7 @@ def _write_website(c): ) ), _SimpleBulkMapping( - header=_StringTable.BingMerchantCenterId, + header=_StringTable.MerchantCenterId, field_to_csv=lambda c: BulkCampaign._write_store_id(c), csv_to_field=lambda c, v: BulkCampaign._read_store_id(c, v) ), diff --git a/bingads/v13/bulk/entities/bulk_campaign_negative_store_criterion.py b/bingads/v13/bulk/entities/bulk_campaign_negative_store_criterion.py index d0eefb61..99682e9c 100644 --- a/bingads/v13/bulk/entities/bulk_campaign_negative_store_criterion.py +++ b/bingads/v13/bulk/entities/bulk_campaign_negative_store_criterion.py @@ -54,7 +54,7 @@ def __init__(self, csv_to_field=lambda c, v: setattr(c, 'campaign_name', v) ), _SimpleBulkMapping( - header=_StringTable.BingMerchantCenterId, + header=_StringTable.MerchantCenterId, field_to_csv=lambda c: bulk_str(c.negative_campaign_criterion.Criterion.StoreId), csv_to_field=lambda c, v: setattr(c.negative_campaign_criterion.Criterion,'StoreId', int(v) if v else None) ), diff --git a/bingads/v13/internal/bulk/bulk_object_factory.py b/bingads/v13/internal/bulk/bulk_object_factory.py index d7cf1e52..6d6a14c8 100644 --- a/bingads/v13/internal/bulk/bulk_object_factory.py +++ b/bingads/v13/internal/bulk/bulk_object_factory.py @@ -16,6 +16,10 @@ class _BulkObjectFactory(): _StringTable.Keyword: _EntityInfo(lambda: BulkKeyword()), _StringTable.CallAdExtension: _EntityInfo(lambda: BulkCallAdExtension()), _StringTable.CampaignCallAdExtension: _EntityInfo(lambda: BulkCampaignCallAdExtension()), + _StringTable.FlyerAdExtension: _EntityInfo(lambda: BulkFlyerAdExtension()), + _StringTable.AccountFlyerAdExtension: _EntityInfo(lambda: BulkAccountFlyerAdExtension()), + _StringTable.CampaignFlyerAdExtension: _EntityInfo(lambda: BulkCampaignFlyerAdExtension()), + _StringTable.AdGroupFlyerAdExtension: _EntityInfo(lambda: BulkAdGroupFlyerAdExtension()), _StringTable.ImageAdExtension: _EntityInfo(lambda: BulkImageAdExtension()), _StringTable.AccountImageAdExtension: _EntityInfo(lambda: BulkAccountImageAdExtension()), _StringTable.CampaignImageAdExtension: _EntityInfo(lambda: BulkCampaignImageAdExtension()), diff --git a/bingads/v13/internal/bulk/csv_headers.py b/bingads/v13/internal/bulk/csv_headers.py index bfdf6461..3982bf01 100644 --- a/bingads/v13/internal/bulk/csv_headers.py +++ b/bingads/v13/internal/bulk/csv_headers.py @@ -127,10 +127,18 @@ class _CsvHeaders: # Callout Ad Extension _StringTable.CalloutText, + + #Flyer Ad Extension + _StringTable.FlyerAdExtension, + _StringTable.AccountFlyerAdExtension, + _StringTable.CampaignFlyerAdExtension, + _StringTable.AdGroupFlyerAdExtension, + _StringTable.FlyerName, + _StringTable.MediaUrls, # Product Target - _StringTable.BingMerchantCenterId, - _StringTable.BingMerchantCenterName, + _StringTable.MerchantCenterId, + _StringTable.MerchantCenterName, _StringTable.ProductCondition1, _StringTable.ProductValue1, _StringTable.ProductCondition2, @@ -317,6 +325,7 @@ class _CsvHeaders: _StringTable.LongHeadline, _StringTable.SquareImageMediaId, _StringTable.SquareLogoMediaId, + _StringTable.ImpressionTrackingUrls, # Ad Scheduling _StringTable.AdSchedule, diff --git a/bingads/v13/internal/bulk/string_table.py b/bingads/v13/internal/bulk/string_table.py index 52aacf43..8564e862 100644 --- a/bingads/v13/internal/bulk/string_table.py +++ b/bingads/v13/internal/bulk/string_table.py @@ -182,6 +182,16 @@ class _StringTable: AdGroupSitelinkAdExtension = "Ad Group Sitelink Ad Extension" CampaignSitelinkAdExtension = "Campaign Sitelink Ad Extension" AccountSitelinkAdExtension = "Account Sitelink Ad Extension" + + + # Flyer Ad Extension + FlyerAdExtension = "Flyer Ad Extension" + AccountFlyerAdExtension = "Account Flyer Ad Extension" + CampaignFlyerAdExtension = "Campaign Flyer Ad Extension" + AdGroupFlyerAdExtension = "Ad Group Flyer Ad Extension" + FlyerName = "Flyer Name" + MediaUrls = "Media Urls" + # Editorial Rejection Reasons PublisherCountries = "Publisher Countries" @@ -208,8 +218,8 @@ class _StringTable: ProductValue7 = "Product Value 7" ProductValue8 = "Product Value 8" - BingMerchantCenterId = "Store Id" - BingMerchantCenterName = "Store Name" + MerchantCenterId = "Store Id" + MerchantCenterName = "Store Name" # App Ad Extension AppAdExtension = "App Ad Extension" @@ -486,6 +496,7 @@ class _StringTable: LongHeadline = "Long Headline" SquareImageMediaId = "Square Image Media Id" SquareLogoMediaId = "Square Logo Media Id" + ImpressionTrackingUrls = "Impression Tracking Urls" #Image Image = "Image" @@ -538,4 +549,4 @@ class _StringTable: CampaignJobFunctionCriterion = 'Campaign Job Function Criterion' CampaignIndustryCriterion = 'Campaign Industry Criterion' - FinalUrlSuffix = "Final Url Suffix" \ No newline at end of file + FinalUrlSuffix = "Final Url Suffix" diff --git a/bingads/v13/internal/extensions.py b/bingads/v13/internal/extensions.py index f9a42e75..ffb7048d 100644 --- a/bingads/v13/internal/extensions.py +++ b/bingads/v13/internal/extensions.py @@ -518,7 +518,7 @@ def field_to_csv_Rsa_TextAssetLinks(entity): contract['pinnedField'] = assetLink.PinnedField if hasattr(assetLink, 'PinnedField') else None assetLinkContracts.append(contract) if len(assetLinkContracts) > 0: - return json.dumps(assetLinkContracts) + return json.dumps(assetLinkContracts, sort_keys = True) return None @@ -1551,12 +1551,16 @@ def parse_combination_rules(combination_list, value): return None rules = value.split('&') - pattern = re.compile(combine_rule_pattern) + pattern = re.compile(combine_rule_pattern, re.IGNORECASE) for rule in rules: m = pattern.match(rule) if m: combination_rule = _CAMPAIGN_OBJECT_FACTORY_V13.create('CombinationRule') - combination_rule.Operator = m.group(1) + combination_rule.Operator = to_operation(m.group(1)) combination_rule.AudienceIds.long.extend([int(id) for id in m.group(2).split(',') if len(id) > 0]) combination_list.CombinationRules.CombinationRule.append(combination_rule) - \ No newline at end of file +def to_operation(op): + if op.lower() == 'and': return 'And' + if op.lower() == 'or': return 'Or' + if op.lower() == 'not': return 'Not' + return none \ No newline at end of file diff --git a/bingads/v13/proxies/campaign_management_service.xml b/bingads/v13/proxies/campaign_management_service.xml index f74faa00..87dc292b 100644 --- a/bingads/v13/proxies/campaign_management_service.xml +++ b/bingads/v13/proxies/campaign_management_service.xml @@ -230,6 +230,13 @@ + + + + + + + @@ -357,7 +364,7 @@ - + @@ -368,7 +375,7 @@ - + @@ -376,6 +383,13 @@ + + + + + + + @@ -438,6 +452,22 @@ + + + + + + + + + + + + + + + + @@ -559,7 +589,7 @@ - + @@ -639,7 +669,7 @@ - + @@ -656,7 +686,7 @@ - + @@ -680,7 +710,7 @@ - + @@ -721,6 +751,8 @@ + + @@ -737,7 +769,7 @@ - + @@ -755,7 +787,7 @@ - + @@ -785,7 +817,7 @@ - + @@ -806,7 +838,7 @@ - + @@ -847,7 +879,7 @@ - + @@ -874,7 +906,7 @@ - + @@ -955,8 +987,8 @@ - - + + @@ -965,7 +997,7 @@ - + @@ -980,7 +1012,7 @@ - + @@ -1032,7 +1064,7 @@ - + @@ -1041,7 +1073,7 @@ - + @@ -1062,7 +1094,7 @@ - + @@ -1115,14 +1147,14 @@ - + - + @@ -1142,7 +1174,7 @@ - + @@ -1159,6 +1191,7 @@ + @@ -1168,6 +1201,16 @@ + + + + + + + + + + @@ -1179,8 +1222,9 @@ - + + @@ -1197,6 +1241,7 @@ + @@ -1244,10 +1289,10 @@ - + - - + + @@ -1294,8 +1339,8 @@ - - + + @@ -1304,7 +1349,7 @@ - + @@ -1334,7 +1379,7 @@ - + @@ -1372,7 +1417,7 @@ - + @@ -1506,7 +1551,7 @@ - + @@ -1515,7 +1560,7 @@ - + @@ -1662,7 +1707,7 @@ - + @@ -1800,10 +1845,10 @@ - + - - + + @@ -1811,7 +1856,7 @@ - + @@ -1834,9 +1879,9 @@ - + - + @@ -1876,9 +1921,9 @@ - + - + @@ -1891,9 +1936,9 @@ - + - + @@ -1984,7 +2029,7 @@ - + @@ -2030,8 +2075,8 @@ - - + + @@ -2071,9 +2116,9 @@ - + - + @@ -2147,11 +2192,11 @@ - + - + - + @@ -2201,6 +2246,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -2235,7 +2300,7 @@ - + @@ -2260,7 +2325,7 @@ - + @@ -2282,6 +2347,7 @@ + @@ -2327,7 +2393,7 @@ - + @@ -2416,7 +2482,7 @@ - + @@ -2444,7 +2510,7 @@ - + @@ -2521,7 +2587,7 @@ - + @@ -2560,7 +2626,7 @@ - + @@ -2568,7 +2634,7 @@ - + @@ -2655,7 +2721,7 @@ - + @@ -2671,7 +2737,7 @@ - + @@ -2706,7 +2772,7 @@ - + @@ -3080,7 +3146,7 @@ - + @@ -3204,9 +3270,9 @@ - + - + @@ -3268,7 +3334,7 @@ - + @@ -3291,7 +3357,7 @@ - + @@ -3353,7 +3419,7 @@ - + @@ -3459,7 +3525,7 @@ - + @@ -3491,14 +3557,14 @@ - + - + @@ -3549,7 +3615,7 @@ - + @@ -3622,7 +3688,7 @@ - + @@ -3655,7 +3721,7 @@ - + @@ -3678,7 +3744,7 @@ - + @@ -3747,7 +3813,7 @@ - + @@ -3764,7 +3830,7 @@ - + @@ -3798,7 +3864,7 @@ - + @@ -3840,7 +3906,7 @@ - + @@ -4026,7 +4092,7 @@ - + @@ -4049,7 +4115,7 @@ - + @@ -4065,7 +4131,7 @@ - + @@ -4105,7 +4171,7 @@ - + @@ -4127,7 +4193,7 @@ - + @@ -4141,7 +4207,7 @@ - + @@ -4156,7 +4222,7 @@ - + @@ -4168,6 +4234,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4186,14 +4340,14 @@ - + - + @@ -4428,7 +4582,7 @@ - + @@ -4462,7 +4616,7 @@ - + @@ -4484,7 +4638,7 @@ - + @@ -4498,7 +4652,7 @@ - + @@ -4514,7 +4668,7 @@ - + @@ -4584,7 +4738,7 @@ - + @@ -4826,7 +4980,7 @@ - + @@ -4850,7 +5004,7 @@ - + @@ -4958,7 +5112,7 @@ - + @@ -4966,7 +5120,7 @@ - + @@ -4994,7 +5148,7 @@ - + @@ -5053,7 +5207,7 @@ - + @@ -5070,7 +5224,7 @@ - + @@ -5113,7 +5267,7 @@ - + @@ -5121,7 +5275,7 @@ - + @@ -5149,7 +5303,7 @@ - + @@ -5244,6 +5398,13 @@ + + + + + + + @@ -5260,7 +5421,7 @@ - + @@ -5274,6 +5435,13 @@ + + + + + + + @@ -5393,7 +5561,7 @@ - + @@ -5412,7 +5580,7 @@ - + @@ -5422,7 +5590,7 @@ - + @@ -5438,6 +5606,20 @@ + + + + 1 + + + + + + + 2 + + + @@ -5460,7 +5642,7 @@ - + @@ -5488,7 +5670,7 @@ - + @@ -5505,7 +5687,7 @@ - + @@ -5517,6 +5699,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5574,6 +5780,28 @@ + + + + + + + + + + + + + + true + + + + + + + + @@ -7513,6 +7741,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -7532,7 +7880,7 @@ - + @@ -7556,7 +7904,7 @@ - + @@ -7580,7 +7928,7 @@ - + @@ -7604,7 +7952,7 @@ - + @@ -7628,7 +7976,7 @@ - + @@ -7652,7 +8000,7 @@ - + @@ -7676,7 +8024,7 @@ - + @@ -7700,7 +8048,7 @@ - + @@ -7724,7 +8072,7 @@ - + @@ -7748,7 +8096,7 @@ - + @@ -7772,7 +8120,7 @@ - + @@ -7796,7 +8144,7 @@ - + @@ -7820,7 +8168,7 @@ - + @@ -7844,7 +8192,7 @@ - + @@ -7868,7 +8216,7 @@ - + @@ -7892,7 +8240,7 @@ - + @@ -7916,7 +8264,7 @@ - + @@ -7940,7 +8288,7 @@ - + @@ -7964,7 +8312,7 @@ - + @@ -7988,7 +8336,7 @@ - + @@ -8012,7 +8360,7 @@ - + @@ -8036,7 +8384,7 @@ - + @@ -8060,7 +8408,7 @@ - + @@ -8084,7 +8432,7 @@ - + @@ -8108,7 +8456,7 @@ - + @@ -8132,7 +8480,7 @@ - + @@ -8156,7 +8504,7 @@ - + @@ -8180,7 +8528,7 @@ - + @@ -8204,7 +8552,7 @@ - + @@ -8228,7 +8576,7 @@ - + @@ -8252,7 +8600,7 @@ - + @@ -8276,11 +8624,35 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8756,6 +9128,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8948,6 +9350,12 @@ + + + + + + @@ -10769,6 +11177,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -11505,10 +12028,33 @@ + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/setup.py b/setup.py index f72460c1..5c45f316 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ except ImportError: from distutils.core import setup -VERSION = '13.0.6' +VERSION = '13.0.7' with open('README.rst', 'r') as f: readme = f.read()