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