def CallRawMethod(self, soap_message):
        """Make an API call by posting raw SOAP XML message.

    Args:
      soap_message: str SOAP XML message.

    Returns:
      tuple Response from the API method.
    """
        # Acquire thread lock.
        self._lock.acquire()

        try:
            buf = AdWordsSoapBuffer(xml_parser=self._config['xml_parser'],
                                    pretty_xml=Utils.BoolTypeConvert(
                                        self._config['pretty_xml']))

            super(AdWordsWebService, self).CallRawMethod(
                buf, Utils.GetNetLocFromUrl(self._op_config['server']),
                soap_message)

            self.__ManageSoap(buf, self._start_time, self._stop_time,
                              {'data': buf.GetBufferAsStr()})
        finally:
            # Release thread lock.
            if self._lock.locked():
                self._lock.release()
        return (self._response, )
 def testProcessingFault(self):
   """Tests whether we can handle a processing fault."""
   try:
     buf = AdWordsSoapBuffer()
     buf.InjectXml(self.__class__.XML_RESPONSE_FAULT2)
     raise AdWordsApiError(buf.GetFaultAsDict())
   except AdWordsApiError, e:
     self.assertEqual(e.message, self.__class__.TRIGGER_MSG3)
 def testStacktraceElement(self):
   """Tests whether we can handle a fault's stacktrace element."""
   try:
     buf = AdWordsSoapBuffer()
     buf.InjectXml(self.__class__.XML_RESPONSE_FAULT1)
     raise AdWordsApiError(buf.GetFaultAsDict())
   except AdWordsApiError, e:
     self.assertEqual(e.message, self.__class__.TRIGGER_MSG2)
     self.assertEqual(int(e.code), self.__class__.TRIGGER_CODE2)
    def testError502(self):
        """Test whether we can handle and report 502 errors."""
        # Temporarily redirect STDOUT into a buffer.
        buf = AdWordsSoapBuffer()
        sys.stdout = buf

        html_code = Utils.ReadFile(os.path.join('data', 'http_error_502.html'))
        print html_code

        # Restore STDOUT.
        sys.stdout = sys.__stdout__

        if not buf.IsHandshakeComplete():
            data = buf.GetBufferAsStr()
        else:
            data = ''

        self.assertEqual(Utils.GetErrorFromHtml(data),
                         self.__class__.TRIGGER_MSG)
    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 testParseError_ETree_PrettyOn(self):
   """Tests that the SOAP buffer parses AdWords errors correctly."""
   self._RunTestWithBuffer(AdWordsSoapBuffer('2', True))
 def testParseError_PyXML_PrettyOff(self):
   """Tests that the SOAP buffer parses AdWords errors correctly."""
   self._RunTestWithBuffer(AdWordsSoapBuffer('1', False))
 def testMalformedBuffer(self):
   """Tests whether we can handle a malformed SOAP buffer."""
   buf = AdWordsSoapBuffer()
   buf.write('JUNK')
   self.assertRaises(MalformedBufferError, buf.GetCallResponseTime)