def ValidateTargeting(targeting): """Validate Targeting object. Args: targeting: dict Targeting object. """ SanityCheck.ValidateTypes(((targeting, dict), )) for key in targeting: if targeting[key] == 'None': continue if key in ('inventoryTargeting', 'geoTargeting'): SanityCheck.ValidateTypes(((targeting[key], dict), )) target = targeting[key] for sub_key in target: SanityCheck.ValidateTypes(((target[sub_key], list), )) for item in target[sub_key]: if key in ('inventoryTargeting', ): SanityCheck.ValidateTypes(((item, (str, unicode)), )) elif key in ('geoTargeting', ): SanityCheck.ValidateTypes(((item, dict), )) for sub_sub_key in item: SanityCheck.ValidateTypes( ((item[sub_sub_key], (str, unicode)), )) # If value is an empty list, remove key from the dictionary. if not target[sub_key]: target = Utils.UnLoadDictKeys(target, [sub_key]) elif key in ('customTargeting', ): ValidateCustomCriteriaSet(targeting[key]) elif key in ('dayPartTargeting', 'userDomainTargeting'): SanityCheck.ValidateTypes(((targeting[key], dict), )) target = targeting[key] for sub_key in target: if sub_key in ('dayParts', ): SanityCheck.ValidateTypes(((target[sub_key], list), )) for item in target[sub_key]: ValidateDayPart(item) elif sub_key in ('domains', ): SanityCheck.ValidateTypes(((target[sub_key], list), )) for item in target[sub_key]: SanityCheck.ValidateTypes(((item, (str, unicode)), )) else: SanityCheck.ValidateTypes( ((target[sub_key], (str, unicode)), ))
def ValidateGeoTargetV13(target): """Validate GeoTarget object. Args: target: dict GeoTarget object. Returns: dict Updated GeoTarget object. """ SanityCheck.ValidateTypes(((target, dict), )) for key in target: if target[key] == 'None': continue if key in ('targetAll', ): SanityCheck.ValidateTypes(((target[key], (str, unicode)), )) data = target[key] else: SanityCheck.ValidateTypes(((target[key], dict), )) geo_target = target[key] for sub_key in geo_target: SanityCheck.ValidateTypes(((geo_target[sub_key], list), )) for item in geo_target[sub_key]: if sub_key in ('circles', ): circle = {} for sub_sub_key in item: SanityCheck.ValidateTypes( ((item[sub_sub_key], (str, unicode)), )) circle[sub_sub_key] = item[sub_sub_key] item = circle else: SanityCheck.ValidateTypes(((item, (str, unicode)), )) # If value is an empty list, remove key from the dictionary. if not geo_target[sub_key]: geo_target = Utils.UnLoadDictKeys(geo_target, [sub_key]) data = geo_target target[key] = data return target
def CallMethod(self, method_name, params, service_name=None, loc=None, request=None): """Make an API call to specified method. Args: method_name: str API method name. params: list List of parameters to send to the API method. [optional] service_name: str API service name. loc: service Locator. request: instance Holder of the SOAP request. Returns: tuple/str Response from the API method. If 'raw_response' flag enabled a string is returned, tuple otherwise. """ # Acquire thread lock. self._lock.acquire() try: if not service_name and self.__service: service_name = self.__service headers = self._headers config = self._config config['data_injects'] = () error = {} # Load/unload version specific authentication and configuration data. if AdWordsSanityCheck.IsJaxbApi(self._op_config['version']): # Set boolean to the format expected by the server, True => true. for key in ['validateOnly', 'partialFailure']: if key in self._headers: self._headers[key] = self._headers[key].lower() # Load/set authentication token. If authentication token has expired, # regenerate it. now = time.time() if ((('authToken' not in headers and 'auth_token_epoch' not in config) or int(now - config['auth_token_epoch']) >= AUTH_TOKEN_EXPIRE) and not 'oauth_enabled' in config): if ('email' not in headers or not headers['email'] or 'password' not in headers or not headers['password']): msg = ( 'Required authentication headers, \'email\' and ' '\'password\', are missing. Unable to regenerate ' 'authentication token.') raise ValidationError(msg) headers['authToken'] = Utils.GetAuthToken( headers['email'], headers['password'], AUTH_TOKEN_SERVICE, LIB_SIG, config['proxy']) config['auth_token_epoch'] = time.time() self._headers = headers self._config = config headers = Utils.UnLoadDictKeys( headers, ['email', 'password', 'useragent']) ns = '/'.join([ 'https://adwords.google.com/api/adwords', self._op_config['group'], self._op_config['version'] ]) default_ns = '/'.join([ 'https://adwords.google.com/api/adwords', self._op_config['default_group'], self._op_config['version'] ]) config['ns_target'] = (ns, 'RequestHeader') if (config['soap_lib'] == SOAPPY and (self._op_config['default_group'] != self._op_config['group'] or self.__service == 'BulkMutateJobService')): from adspygoogle.adwords.soappy import SERVICE_TYPES data_injects = [] for header in headers: if headers[header]: data_injects.append((header, 'ns1:%s' % header)) data_injects.append( ('<RequestHeader>', '<RequestHeader xmlns="%s" xmlns:ns1="%s">' % (ns, default_ns))) data_injects.append( ('<SOAP-ENV:Body xmlns="%s">' % ns, '<SOAP-ENV:Body xmlns="%s" xmlns:ns1="%s">' % (ns, default_ns))) for item in SERVICE_TYPES: if (item['group'] == self._op_config['default_group'] and re.compile( '<%s>|<%s ' % (item['attr'], item['attr'])).findall(params)): # TODO(api.sgrinberg): Find a more elegant solution that doesn't # involve manual triggering for attributes that show up in both # groups. if ((self._op_config['group'] == 'o' and item['attr'] == 'urls') or (self.__service == 'TrafficEstimatorService' and item['attr'] == 'maxCpc') or item['attr'] == 'selector' or item['attr'] == 'operator'): continue if self.__service != 'BulkMutateJobService': data_injects.append( (' xsi3:type="%s">' % item['type'], '>')) data_injects.append(('<%s>' % item['attr'], '<ns1:%s>' % item['attr'])) data_injects.append(('<%s ' % item['attr'], '<ns1:%s ' % item['attr'])) data_injects.append(('</%s>' % item['attr'], '</ns1:%s>' % item['attr'])) config['data_injects'] = tuple(data_injects) else: headers['useragent'] = headers['userAgent'] headers = Utils.UnLoadDictKeys(headers, ['authToken', 'userAgent']) config = Utils.UnLoadDictKeys( config, ['ns_target', 'auth_token_epoch']) buf = AdWordsSoapBuffer(xml_parser=self._config['xml_parser'], pretty_xml=Utils.BoolTypeConvert( self._config['pretty_xml'])) start_time = time.strftime('%Y-%m-%d %H:%M:%S') response = super(AdWordsWebService, self).CallMethod( headers, config, method_name, params, buf, AdWordsSanityCheck.IsJaxbApi(self._op_config['version']), LIB_SIG, LIB_URL, service_name, loc, request) stop_time = time.strftime('%Y-%m-%d %H:%M:%S') # Restore list type which was overwritten by SOAPpy. if config['soap_lib'] == SOAPPY and isinstance(response, tuple): from adspygoogle.common.soappy import MessageHandler holder = [] for element in response: holder.append( MessageHandler.RestoreListType( element, ('value', 'partialFailureErrors', 'conversionTypes'))) response = tuple(holder) if isinstance(response, dict) or isinstance(response, Error): error = response if not Utils.BoolTypeConvert(self.__config['raw_debug']): self.__ManageSoap(buf, start_time, stop_time, error) finally: # Release thread lock. if self._lock.locked(): self._lock.release() if Utils.BoolTypeConvert(self._config['raw_response']): return response return response
def ValidateTargeting(targeting, web_services): """Validate Targeting object. Args: targeting: dict Targeting object. web_services: module Web services. Returns: Targeting instance. """ if ZsiSanityCheck.IsPyClass(targeting): return targeting SanityCheck.ValidateTypes(((targeting, dict), )) for key in targeting: if targeting[key] == 'None' or not targeting[key]: continue if key in ('inventoryTargeting', 'geoTargeting'): SanityCheck.ValidateTypes(((targeting[key], dict), )) target = targeting[key] for sub_key in target: SanityCheck.ValidateTypes(((target[sub_key], list), )) targets = [] for item in target[sub_key]: if key in ('inventoryTargeting', ): SanityCheck.ValidateTypes(((item, (str, unicode)), )) targets.append(item) elif key in ('geoTargeting', ): SanityCheck.ValidateTypes(((item, dict), )) if 'xsi_type' in item: location = ZsiSanityCheck.GetPyClass( item['xsi_type'], web_services) else: msg = 'The \'xsi_type\' of the geo targeting location is missing.' raise ValidationError(msg) for sub_sub_key in item: SanityCheck.ValidateTypes( ((item[sub_sub_key], (str, unicode)), )) location.__dict__.__setitem__( '_%s' % sub_sub_key, item[sub_sub_key]) targets.append(location) # If value is an empty list, remove key from the dictionary. if not target[sub_key]: target = Utils.UnLoadDictKeys(target, [sub_key]) target[sub_key] = targets data = target elif key in ('customTargeting', ): data = ValidateCustomCriteriaSet(targeting[key], web_services) elif key in ('dayPartTargeting', 'userDomainTargeting'): SanityCheck.ValidateTypes(((targeting[key], dict), )) target = targeting[key] for sub_key in target: if sub_key in ('dayParts', ): SanityCheck.ValidateTypes(((target[sub_key], list), )) targets = [] for item in target[sub_key]: ValidateDayPart(item) elif sub_key in ('domains', ): SanityCheck.ValidateTypes(((target[sub_key], list), )) for item in target[sub_key]: SanityCheck.ValidateTypes(((item, (str, unicode)), )) else: SanityCheck.ValidateTypes( ((target[sub_key], (str, unicode)), )) data = target return data
def CallMethod(self, method_name, params, service_name=None, loc=None, request=None): """Make an API call to specified method. Args: method_name: str API method name. params: list List of parameters to send to the API method. [optional] service_name: str API service name. loc: service Locator. request: instance Holder of the SOAP request. Returns: tuple/str Response from the API method. If 'raw_response' flag enabled a string is returned, tuple otherwise. """ # Acquire thread lock. self._lock.acquire() try: headers = self._headers config = self._config config['data_injects'] = () error = {} # Load/set authentication token. If authentication token has expired, # regenerate it. now = time.time() if ((('authToken' not in headers and 'auth_token_epoch' not in config) or int(now - config['auth_token_epoch']) >= AUTH_TOKEN_EXPIRE)): headers['authToken'] = Utils.GetAuthToken( headers['email'], headers['password'], AUTH_TOKEN_SERVICE, LIB_SIG, config['proxy']) config['auth_token_epoch'] = time.time() self._headers = headers self._config = config headers = Utils.UnLoadDictKeys(Utils.CleanUpDict(headers), ['email', 'password']) name_space = '/'.join([ 'https://www.google.com/apis/ads/publisher', self._op_config['version'] ]) config['ns_target'] = (name_space, 'RequestHeader') # Load new authentication headers, starting with version v201103. data_injects = [] if self.__op_config['version'] > 'v201101': new_headers = {} for key in headers: if key == 'authToken' and headers[key]: if config['soap_lib'] == SOAPPY: data_injects.append( ('<authentication>', '<authentication xsi3:type="ClientLogin">')) config['data_injects'] = tuple(data_injects) else: config['auth_type'] = 'ClientLogin' new_headers['authentication'] = { 'token': headers['authToken'] } elif key == 'oAuthToken' and headers[key]: # TODO(api.sgrinberg): Add support for OAuth. pass else: new_headers[key] = headers[key] headers = new_headers buf = DfpSoapBuffer(xml_parser=self._config['xml_parser'], pretty_xml=Utils.BoolTypeConvert( self._config['pretty_xml'])) start_time = time.strftime('%Y-%m-%d %H:%M:%S') response = super(DfpWebService, self).CallMethod( headers, config, method_name, params, buf, DfpSanityCheck.IsJaxbApi(self._op_config['version']), LIB_SIG, LIB_URL, service_name, loc, request) stop_time = time.strftime('%Y-%m-%d %H:%M:%S') # Restore list type which was overwritten by SOAPpy. if config['soap_lib'] == SOAPPY and isinstance(response, tuple): from adspygoogle.common.soappy import MessageHandler holder = [] for element in response: holder.append( MessageHandler.RestoreListType( element, ('results', 'afcFormats', 'sizes', 'targetedAdUnitIds', 'excludedAdUnitIds', 'targetedPlacementIds', 'frequencyCaps', 'creativeSizes'))) response = tuple(holder) if isinstance(response, dict) or isinstance(response, Error): error = response if not Utils.BoolTypeConvert(self.__config['raw_debug']): self.__ManageSoap(buf, start_time, stop_time, error) finally: # Release thread lock. if self._lock.locked(): self._lock.release() if Utils.BoolTypeConvert(self._config['raw_response']): return response return response