#!/usr/bin/python # # Copyright 2009 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Validation and type conversion functions.""" __author__ = 'api.sgrinberg@gmail.com (Stan Grinberg)' import cgi import re from aw_api import SanityCheck as glob_sanity_check from aw_api import Utils from aw_api.Errors import MissingPackageError from aw_api.soappy_toolkit import MIN_SOAPPY_VERSION try: import SOAPpy except ImportError: msg = 'SOAPpy v%s or newer is required.' % MIN_SOAPPY_VERSION raise MissingPackageError(msg) else: if (map(eval, SOAPpy.version.__version__.split('.')) < (list(map(eval, MIN_SOAPPY_VERSION.split('.'))))): msg = 'SOAPpy v%s or newer is required.' % MIN_SOAPPY_VERSION raise MissingPackageError(msg) def UnType(item): """Convert given string into untyped type. Args: item: str string to untype. Returns: untypedType string converted into untypedType. """ glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) # HTML encode non-complex strings. Complex strings would be XML snippets, # like GoogleSearch. pattern = re.compile('<.*>|') if pattern.search(item) is None: pattern = re.compile('&#(x\w\w|\d{3});') result = pattern.findall(item) # Escape only ASCII characters. if not result: item = cgi.escape(item) return SOAPpy.Types.untypedType(item) def IsUnTypedClass(obj): """Return True if a given object is of type SOAPpy.Types.untypedType, False otherwise. Args: obj: object an object to check. Returns: bool True if a given object is untyped, False otherwise. """ return isinstance(obj, SOAPpy.Types.untypedType) def ValidateAccountInfoV13(acct_info): """Validate AccountInfo object. Args: acct_info: dict AccountInfo object with updated values. """ glob_sanity_check.ValidateTypes(((acct_info, dict),)) for key in acct_info: if key == 'defaultNetworkTargeting': glob_sanity_check.ValidateTypes(((acct_info[key], list),)) items = [] for sub_key in acct_info[key]: glob_sanity_check.ValidateTypes(((sub_key, (str, unicode)),)) items.append('%s' % sub_key) acct_info[key] = UnType(''.join(items)) elif key == 'emailPromotionsPreferences': glob_sanity_check.ValidateTypes(((acct_info[key], dict),)) for sub_key in acct_info[key]: glob_sanity_check.ValidateTypes(((acct_info[key][sub_key], (str, unicode)),)) acct_info[key][sub_key] = UnType(acct_info[key][sub_key]) else: glob_sanity_check.ValidateTypes(((acct_info[key], (str, unicode)),)) def ValidateAdGroupV13(ad_group): """Validate AdGroup object. Args: ad_group: dict information for the ad group. """ glob_sanity_check.ValidateTypes(((ad_group, dict),)) for key in ad_group: if IsUnTypedClass(ad_group[key]): continue glob_sanity_check.ValidateTypes(((ad_group[key], (str, unicode)),)) ad_group[key] = UnType(ad_group[key]) def ValidateAdV13(ad): """Validate Ad object. Args: ad: dict information for the ad. """ glob_sanity_check.ValidateTypes(((ad, dict),)) for key in ad: if key == 'markupLanguages' or key == 'mobileCarriers': glob_sanity_check.ValidateTypes(((ad[key], list),)) for item in ad[key]: glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) item = UnType(item) elif (key == 'image' or key == 'businessImage' or key == 'customIcon' or key == 'productImage' or key == 'video'): glob_sanity_check.ValidateTypes(((ad[key], dict),)) for sub_key in ad[key]: glob_sanity_check.ValidateTypes(((ad[key][sub_key], (str, unicode)),)) ad[key][sub_key] = UnType(ad[key][sub_key]) else: glob_sanity_check.ValidateTypes(((ad[key], (str, unicode)),)) if key == 'description1' or key == 'description2' or key == 'headline': ad[key] = Utils.MakeTextXMLReady(ad[key]) ad[key] = UnType(ad[key]) def ValidateOptimizerSettingsV13(optimizer): """Validate BudgetOptimizerSettings or ConversionOptimizerSettings object. Args: optimizer: dict optimizer settings for this entity. Returns: str optimizer settings converted into str type. """ glob_sanity_check.ValidateTypes(((optimizer, dict),)) items = [] for key in optimizer: items.append('<%s>%s' % (key, optimizer[key], key)) return ''.join(items) def ValidateLanguageTargetV13(language_target): """Validate LanguageTarget object. Args: language_target: list languages targeted by this entity. Returns: str languages targeted converted into str type. """ glob_sanity_check.ValidateTypes(((language_target, list),)) items = [] for item in language_target: glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) items.append('%s' % item) return ''.join(items) def ValidateGeoTargetV13(geo_target): """Validate GeoTarget object. Args: geo_target: dict geographic targeting rules for this entity. Returns: str geographic targeting converted into str type. """ glob_sanity_check.ValidateTypes(((geo_target, dict),)) items = [] for key in geo_target: if key == 'targetAll': glob_sanity_check.ValidateTypes(((geo_target[key], (str, unicode)),)) items.append('<%s>%s' % (key, geo_target[key], key)) elif key == 'cityTargets': glob_sanity_check.ValidateTypes(((geo_target[key], dict),)) items.append('<%s>' % key) for sub_key in geo_target[key]: glob_sanity_check.ValidateTypes(((geo_target[key][sub_key], list),)) for item in geo_target[key][sub_key]: items.append('<%s>%s' % (sub_key, item, sub_key)) items.append('' % key) elif key == 'countryTargets': glob_sanity_check.ValidateTypes(((geo_target[key], dict),)) items.append('<%s>' % key) for sub_key in geo_target[key]: glob_sanity_check.ValidateTypes(((geo_target[key][sub_key], list),)) for item in geo_target[key][sub_key]: items.append('<%s>%s' % (sub_key, item, sub_key)) items.append('' % key) elif key == 'metroTargets': glob_sanity_check.ValidateTypes(((geo_target[key], dict),)) items.append('<%s>' % key) for sub_key in geo_target[key]: glob_sanity_check.ValidateTypes(((geo_target[key][sub_key], list),)) for item in geo_target[key][sub_key]: items.append('<%s>%s' % (sub_key, item, sub_key)) items.append('' % key) elif key == 'regionTargets': glob_sanity_check.ValidateTypes(((geo_target[key], dict),)) items.append('<%s>' % key) for sub_key in geo_target[key]: glob_sanity_check.ValidateTypes(((geo_target[key][sub_key], list),)) for item in geo_target[key][sub_key]: items.append('<%s>%s' % (sub_key, item, sub_key)) items.append('' % key) elif key == 'proximityTargets': glob_sanity_check.ValidateTypes(((geo_target[key], dict),)) items.append('<%s>' % key) for sub_key in geo_target[key]: glob_sanity_check.ValidateTypes(((geo_target[key][sub_key], list),)) for item in geo_target[key][sub_key]: items.append('<%s>' % sub_key) glob_sanity_check.ValidateTypes(((item, dict),)) for sub_sub_key in item: glob_sanity_check.ValidateTypes(((item[sub_sub_key], (str, unicode)),)) items.append('<%s>%s' % (sub_sub_key, item[sub_sub_key], sub_sub_key)) items.append('' % sub_key) items.append('' % key) else: pass return ''.join(items) def ValidateNetworkTargetV13(network_target): """Validate NetworkTarget object. Args: network_target: list advertising networks targeted by this entity. Returns: str adertising networks converted into str type. """ glob_sanity_check.ValidateTypes(((network_target, list),)) items = [] for item in network_target: glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) items.append('%s' % item) return ''.join(items) def ValidateAdScheduleV13(ad_schedule): """Validate AdSchedule object. Args: ad_schedule: dict ad scheduling setting for this entity. Returns: str ad scheduling setting converted into str type. """ glob_sanity_check.ValidateTypes(((ad_schedule, dict),)) items = [] for key in ad_schedule: if key == 'status': glob_sanity_check.ValidateTypes(((ad_schedule[key], (str, unicode)),)) items.append('<%s>%s' % (key, ad_schedule[key], key)) elif key == 'intervals': glob_sanity_check.ValidateTypes(((ad_schedule[key], list),)) for item in ad_schedule[key]: glob_sanity_check.ValidateTypes(((item, dict),)) sub_items = [''] for sub_key in item: glob_sanity_check.ValidateTypes(((item[sub_key], (str, unicode)),)) sub_items.append('<%s>%s' % (sub_key, item[sub_key], sub_key)) sub_items.append('') items.append(''.join(sub_items)) else: pass return ''.join(items) def ValidateCampaignV13(campaign): """Validate Campaign object. Args: campaign: dict information for the campaign. """ glob_sanity_check.ValidateTypes(((campaign, dict),)) for key in campaign: if (key == 'budgetAmount' or key == 'budgetPeriod' or key == 'contentTargeting' or key == 'endDay' or key == 'id' or key == 'name' or key == 'startDay' or key == 'status'): glob_sanity_check.ValidateTypes(((campaign[key], (str, unicode)),)) campaign[key] = UnType(campaign[key]) elif (key == 'budgetOptimizerSettings' or key == 'conversionOptimizerSettings'): campaign[key] = UnType(ValidateOptimizerSettingsV13(campaign[key])) elif key == 'geoTargeting': campaign[key] = UnType(ValidateGeoTargetV13(campaign[key])) elif key == 'languageTargeting': campaign[key] = UnType(ValidateLanguageTargetV13(campaign[key])) elif key == 'networkTargeting': campaign[key] = UnType(ValidateNetworkTargetV13(campaign[key])) elif key == 'schedule': campaign[key] = UnType(ValidateAdScheduleV13(campaign[key])) else: pass def ValidateCriterionV13(criterion): """Validate criterion object. Args: criterion: dict information for the criterion. """ glob_sanity_check.ValidateTypes(((criterion, dict),)) for key in criterion: glob_sanity_check.ValidateTypes(((criterion[key], (str, unicode)),)) if key == 'text': criterion[key] = Utils.MakeTextXMLReady(criterion[key]) criterion[key] = UnType(criterion[key]) def ValidateSeedKeywordV13(seed_keyword): """Validate SeedKeyword object. Args: seed_keyword: dict information for keyword to derive variations from. """ glob_sanity_check.ValidateTypes(((seed_keyword, dict),)) for key in seed_keyword: glob_sanity_check.ValidateTypes(((seed_keyword[key], (str, unicode)),)) seed_keyword[key] = UnType(seed_keyword[key]) def ValidateDemographicsTargetV13(demo): """Validate DemographicsTarget object. Args: demo: dict demographics targeting criteria. """ glob_sanity_check.ValidateTypes(((demo, dict),)) for key in demo: glob_sanity_check.ValidateTypes(((demo[key], (str, unicode)),)) demo[key] = UnType(demo[key]) def ValidateLanguageGeoTargetingV13(targeting): """Validate LanguageGeoTargeting object. Args: targeting: dict language and geo targeting information. """ glob_sanity_check.ValidateTypes(((targeting, dict),)) for key in targeting: glob_sanity_check.ValidateTypes(((targeting[key], list),)) for sub_key in targeting[key]: glob_sanity_check.ValidateTypes(((sub_key, (str, unicode)),)) def ValidateKeywordTrafficRequestV13(request): """Validate KeywordTrafficRequest object. Args: request: dict keyword traffic request. """ glob_sanity_check.ValidateTypes(((request, dict),)) for key in request: glob_sanity_check.ValidateTypes(((request[key], (str, unicode)),)) request[key] = UnType(request[key]) def ValidateKeywordRequestV13(request): """Validate KeywordRequest object. Args: request: dict keyword request. Returns: str keyword request converted into str type. """ glob_sanity_check.ValidateTypes(((request, dict),)) items = [] for key in request: glob_sanity_check.ValidateTypes(((request[key], (str, unicode)),)) items.append('<%s>%s' % (key, request[key], key)) return ''.join(items) def ValidateAdGroupRequestV13(request): """Validate AdGroupRequest object. Args: request: dict ad group request. Returns: str ad group request converted into str type. """ glob_sanity_check.ValidateTypes(((request, dict),)) items = [] for key in request: if key == 'keywordRequests': items.append('') glob_sanity_check.ValidateTypes(((request[key], list),)) for item in request[key]: items.append(ValidateKeywordRequestV13(item)) items.append('') else: glob_sanity_check.ValidateTypes(((request[key], (str, unicode)),)) items.append('<%s>%s' % (key, request[key], key)) return ''.join(items) def ValidateCampaignRequestV13(request): """Validate CampaignRequest object. Args: request: dict campaign request. Returns: str campaign request converted into str type. """ glob_sanity_check.ValidateTypes(((request, dict),)) items = [] for key in request: if key == 'adGroupRequests': glob_sanity_check.ValidateTypes(((request[key], list),)) items.append('') for item in request[key]: items.append(ValidateAdGroupRequestV13(item)) items.append('') elif key == 'geoTargeting': glob_sanity_check.ValidateTypes(((request[key], dict),)) items.append(('%s' % ValidateGeoTargetV13(request[key]))) elif key == 'id': glob_sanity_check.ValidateTypes(((request[key], (str, unicode)),)) items.append('<%s>%s' % (key, request[key], key)) elif key == 'languageTargeting': glob_sanity_check.ValidateTypes(((request[key], list),)) items.append('<%s>%s' % (key, ValidateLanguageTargetV13(request[key]), key)) elif key == 'networkTargeting': glob_sanity_check.ValidateTypes(((request[key], list),)) items.append('<%s>%s' % (key, ValidateNetworkTargetV13(request[key]), key)) else: pass return ''.join(items) def ValidateDefinedReportJobV13(job, name_space): """Validate DefinedReportJob object. Args: job: dict report job object. name_space: str namespace to use for this ReportJob. Returns: instance untyped instance of ReportJob. """ items = [] for key in job: if (key == 'adWordsType' or key == 'crossClient' or key == 'endDay' or key == 'includeZeroImpression' or key == 'keywordType' or key == 'name' or key == 'selectedReportType' or key == 'startDay'): glob_sanity_check.ValidateTypes(((job[key], (str, unicode)),)) items.append('<%s>%s' % (key, job[key], key)) else: glob_sanity_check.ValidateTypes(((job[key], list),)) for item in job[key]: glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) items.append('<%s>%s' % (key, item, key)) # Explicitly set job's namespace and type. job = UnType(''.join(items)) job._setAttr('xmlns:impl', name_space) job._setAttr('xsi3:type', 'impl:DefinedReportJob') return job # TODO(api.sgrinberg): Add validation for Get/Mutate calls. def ValidateOperation(operation): """Validate Operation object. Args: operation: dict operation object. """ pass def ValidateSelector(selector): """Validate Selector object. Args: selector: dict selector object. """ pass