Exemple #1
0
    def __MakeRequest(self, url, headers=None, fileobj=None, payload=None):
        """Performs an HTTPS request and slightly processes the response.

    If fileobj is provided, saves the body to file instead of including it
    in the return value.

    Args:
      url: str Resource for the request line.
      headers: dict Headers to send along with the request.
      fileobj: file File to save to (optional).
      payload: str Xml to POST (optional).

    Returns:
      str Report data as a string if fileobj=None, otherwise None
    """
        headers = headers or {}
        request_url = self._op_config['server'] + url

        orig_payload = payload

        if Utils.BoolTypeConvert(self._config['compress']):
            buffer = StringIO.StringIO()
            gzip_file = gzip.GzipFile(mode='wb', fileobj=buffer)
            gzip_file.write(payload)
            gzip_file.close()
            payload = buffer.getvalue()
            headers['Content-Length'] = str(len(payload))

        start_time = time.strftime('%Y-%m-%d %H:%M:%S')
        request = urllib2.Request(request_url, payload, headers)
        try:
            try:
                response = urllib2.urlopen(request)
                response_code = response.code
                response_headers = response.info().headers
                if response.info().get('Content-Encoding') == 'gzip':
                    response = gzip.GzipFile(fileobj=StringIO.StringIO(
                        response.read()),
                                             mode='rb')
                if fileobj:
                    self.__DumpToFile(response, fileobj)
                    return None
                else:
                    return response.read()
            except urllib2.HTTPError, e:
                response = e
                response_code = response.code
                response_headers = response.info().headers
                if response.info().get('Content-Encoding') == 'gzip':
                    response = gzip.GzipFile(fileobj=StringIO.StringIO(
                        response.read()),
                                             mode='rb')
                error = response.read()
                self.__CheckForXmlError(response_code, error)
                raise AdWordsError('%s %s' % (str(e), error))
            except urllib2.URLError, e:
                response = e
                response_code = '---'
                response_headers = []
                raise AdWordsError(str(e))
  def _HandleLogsAndErrors(self, buf, start_time, stop_time, error=None):
    """Manage SOAP XML message.

    Args:
      buf: SoapBuffer SOAP buffer.
      start_time: str Time before service call was invoked.
      stop_time: str Time after service call was invoked.
      [optional]
      error: dict Error, if any.
    """
    if error is None:
      error = {}
    try:
      # Update the number of units and operations consumed by API call.
      if buf.GetCallUnits() and buf.GetCallOperations():
        self._config['units'][0] += int(buf.GetCallUnits())
        self._config['operations'][0] += int(buf.GetCallOperations())
        self._config['last_units'][0] = int(buf.GetCallUnits())
        self._config['last_operations'][0] = int(buf.GetCallOperations())

      handlers = self.__GetLogHandlers(buf)
      fault = super(GenericAdWordsService, self)._ManageSoap(
          buf, handlers, LIB_URL, start_time, stop_time, error)
      if fault:
        # Raise a specific error, subclass of AdWordsApiError.
        if 'detail' in fault and fault['detail']:
          if 'errors' in fault['detail']:
            error_type = fault['detail']['errors'][0]['type']
            if error_type in ERRORS: raise ERRORS[str(error_type)](fault)
        if isinstance(fault, basestring):
          raise AdWordsError(fault)
        elif isinstance(fault, dict):
          raise AdWordsApiError(fault)
    except AdWordsApiError, e:
      raise e
Exemple #3
0
  def DownloadBulkJob(self, job_id, wait_secs=30, max_polls=60):
    """Return results of the bulk mutate job or None if there was a failure.

    Args:
      job_id: str Bulk mutate job id.
      wait_secs: int Time in seconds to wait between each poll.
      max_polls: int Maximum number of polls to perform.

    Returns:
      list Results of the bulk mutate job or None if there was a failure.
    """
    SanityCheck.ValidateTypes(((job_id, (str, unicode)), (wait_secs, int),
                               (max_polls, int)))

    # Wait for bulk muate job to complete.
    selector = {
        'jobIds': [job_id]
    }
    job = self.Get(selector)[0]
    status = job['status']
    num_parts = job['numRequestParts']
    num_parts_recieved = job['numRequestPartsReceived']

    # Were all parts of the job uploaded?
    if num_parts != num_parts_recieved:
      return None

    num_polls = 1
    while (status != 'COMPLETED' and status != 'FAILED' and
           num_polls < max_polls):
      if Utils.BoolTypeConvert(self._config['debug']):
        print 'Bulk mutate job status: %s' % status
      time.sleep(wait_secs)
      status = self.Get(selector)[0]['status']
      num_polls += 1

    if status != 'COMPLETED' and status != 'FAILED' and num_polls >= max_polls:
      msg = ('The job with id \'%s\' has exceeded max_polls of \'%s\'.'
             % (job_id, max_polls))
      raise AdWordsError(msg)

    if status == 'FAILED':
      if Utils.BoolTypeConvert(self._config['debug']):
        print 'Bulk mutate job failed'
        return None

    if Utils.BoolTypeConvert(self._config['debug']):
      print 'Bulk mutate job completed successfully'

    # Get results for each part of the job.
    res = []
    for part in xrange(int(num_parts)):
      selector = {
          'jobIds': [job_id],
          'resultPartIndex': str(part)
      }
      res.append(self.Get(selector)[0])
    return res
 def testError(self):
   """Tests whether we can catch an AdWordsErrors.AdWordsError exception."""
   try:
     try:
       self.__class__.dummy_client.GetAccountService(
           self.__class__.SERVER, self.__class__.VERSION,
           HTTP_PROXY).GetAccountInfo()
     except AdWordsError, e:
       raise AdWordsError(e.message)
   except AdWordsError, e:
     try:
       self.assertEqual(str(e), self.__class__.TRIGGER_MSG1)
     except:
       self.assertEqual(str(e), self.__class__.TRIGGER_MSG2)
    def __GenerateHeaders(self,
                          return_micros=None,
                          skip_report_header=None,
                          skip_report_summary=None):
        """Generates the headers to use for the report download.

    Args:
      return_micros: bool whether or not to use micros for money.
      skip_report_header: A boolean indicating whether to include a header row
          containing the report name and date range. If false or not specified,
          report output will include the header row.
      skip_report_summary: A boolean indicating whether to include a summary row
          containing the report totals. If false or not specified, report output
          will include the summary row.

    Returns:
      dict Dictionary containing all the headers for the request
    """
        headers = {}
        if 'clientCustomerId' in self._headers:
            headers['clientCustomerId'] = self._headers['clientCustomerId']

        # Apply OAuth2 headers
        self._headers['oauth2credentials'].apply(headers)

        if skip_report_header:
            headers.update({'skipReportHeader': str(skip_report_header)})

        if skip_report_summary:
            headers.update({'skipReportSummary': str(skip_report_summary)})

        if return_micros is not None:
            if self._op_config[
                    'version'] == FINAL_RETURN_MONEY_IN_MICROS_VERSION:
                headers['returnMoneyInMicros'] = str(return_micros)
            else:
                raise AdWordsError(
                    'returnMoneyInMicros isn\'t supported in this'
                    ' version.')

        headers['developerToken'] = self._headers['developerToken']
        headers['User-Agent'] = self._headers['userAgent']
        if Utils.BoolTypeConvert(self._config['compress']):
            headers['Accept-Encoding'] = 'gzip'
            headers['User-Agent'] += ',gzip'
            headers['Content-Encoding'] = 'gzip'
        return headers
Exemple #6
0
    def GetCampaigns(self, client_customer_id):
        """Returns a client account's Campaigns that haven't been removed.

    Args:
      client_customer_id: str Client Customer Id used to retrieve Campaigns.

    Returns:
      list List of Campaign data objects.
    """
        self.client.SetClientCustomerId(client_customer_id)
        self.client.use_mcc = False
        # A somewhat hackish workaround for "The read operation timed out" error,
        # which could be triggered on AppEngine's end if the request is too large
        # and is taking too long.
        max_tries = 3
        today = time.strftime('%Y%m%d', time.localtime())
        for i in xrange(1, max_tries + 1):
            try:
                selector = {
                    'fields': ['Id', 'Name', 'Status', 'BudgetId', 'Amount'],
                    'predicates': [{
                        'field': 'Status',
                        'operator': 'NOT_EQUALS',
                        'values': ['REMOVED']
                    }],
                    'dateRange': {
                        'min': today,
                        'max': today
                    }
                }
                campaigns = self.client.GetCampaignService().Get(selector)[0]
                if int(campaigns['totalNumEntries']) > 0:
                    return campaigns['entries']
                else:
                    return None
            except Exception, e:
                if i == max_tries:
                    raise AdWordsError(e)
                continue
    def __ManageSoap(self, buf, start_time, stop_time, error={}):
        """Manage SOAP XML message.

    Args:
      buf: SoapBuffer SOAP buffer.
      start_time: str Time before service call was invoked.
      stop_time: str Time after service call was invoked.
      [optional]
      error: dict Error, if any.
    """
        try:
            # Update the number of units and operations consumed by API call.
            if buf.GetCallUnits() and buf.GetCallOperations():
                self._config['units'][0] += int(buf.GetCallUnits())
                self._config['operations'][0] += int(buf.GetCallOperations())
                self._config['last_units'][0] = int(buf.GetCallUnits())
                self._config['last_operations'][0] = int(
                    buf.GetCallOperations())

            # Set up log handlers.
            handlers = [{
                'tag': 'xml_log',
                'name': 'soap_xml',
                'data': ''
            }, {
                'tag':
                'request_log',
                'name':
                'request_info',
                'data':
                str('host=%s service=%s method=%s operator=%s '
                    'responseTime=%s operations=%s units=%s requestId=%s' %
                    (Utils.GetNetLocFromUrl(self._url), buf.GetServiceName(),
                     buf.GetCallName(), buf.GetOperatorName(),
                     buf.GetCallResponseTime(), buf.GetCallOperations(),
                     buf.GetCallUnits(), buf.GetCallRequestId()))
            }, {
                'tag': '',
                'name': 'adwords_api_lib',
                'data': ''
            }]

            fault = super(AdWordsWebService,
                          self)._ManageSoap(buf, handlers, LIB_URL, ERRORS,
                                            start_time, stop_time, error)
            if fault:
                # Raise a specific error, subclass of AdWordsApiError.
                if 'detail' in fault:
                    if 'code' in fault['detail']:
                        code = int(fault['detail']['code'])
                        if code in ERRORS: raise ERRORS[code](fault)
                    elif 'errors' in fault['detail']:
                        type = fault['detail']['errors'][0]['type']
                        if type in ERRORS: raise ERRORS[str(type)](fault)

                if isinstance(fault, str):
                    raise AdWordsError(fault)
                elif isinstance(fault, dict):
                    raise AdWordsApiError(fault)
        except AdWordsApiError, e:
            raise e