def DownloadReportToFile(report_job_id, export_format, service, outfile):
  """Download report data and write to a file.

  Args:
    report_job_id: str ID of the report job.
    export_format: str Export format for the report file.
    service: GenericDfpService A service pointing to the ReportService.
    outfile: file the file object to write to. If no file handle is passed in, a
          temporary file will be created.
  """
  SanityCheck.ValidateTypes(((report_job_id, (str, unicode)),))

  # Wait for report to complete.
  status = service.GetReportJob(report_job_id)[0]['reportJobStatus']
  while status != 'COMPLETED' and status != 'FAILED':
    if Utils.BoolTypeConvert(service._config['debug']):
      print 'Report job status: %s' % status
    time.sleep(30)
    status = service.GetReportJob(report_job_id)[0]['reportJobStatus']

  if status == 'FAILED':
    if Utils.BoolTypeConvert(service._config['debug']):
      print 'Report process failed'
    return ''
  else:
    if Utils.BoolTypeConvert(service._config['debug']):
      print 'Report has completed successfully'

  # Get report download URL.
  report_url = service.GetReportDownloadURL(report_job_id, export_format)[0]
  response = urllib2.urlopen(report_url)
  while True:
    chunk = response.read(_CHUNK_SIZE)
    if not chunk: break
    outfile.write(chunk)
    def __LogRequest(self, xml_log_data):
        """Logs the Report Download request.

    Args:
      xml_log_data: str Data to log for this request.
    """
        log_handlers = self.__GetLogHandlers()
        for handler in log_handlers:
            handler['target'] = Logger.NONE
            if handler['tag'] == 'xml_log':
                handler['data'] += xml_log_data
        for handler in log_handlers:
            if (handler['tag']
                    and Utils.BoolTypeConvert(self._config[handler['tag']])):
                handler['target'] = Logger.FILE
            # If debugging is On, raise handler's target two levels,
            #   NONE -> CONSOLE
            #   FILE -> FILE_AND_CONSOLE.
            if Utils.BoolTypeConvert(self._config['debug']):
                handler['target'] += 2

            if (handler['target'] != Logger.NONE and handler['data']
                    and handler['data'] != 'None'
                    and handler['data'] != 'DEBUG: '):
                self._logger.Log(handler['name'],
                                 handler['data'],
                                 log_level=Logger.DEBUG,
                                 log_handler=handler['target'])
  def DownloadReport(self, report_job_id, export_format):
    """Download and return report data.

    Args:
      report_job_id: str ID of the report job.
      export_format: str Export format for the report file.

    Returns:
      str Report data or empty string if report failed.
    """
    SanityCheck.ValidateTypes(((report_job_id, (str, unicode)),))

    # Wait for report to complete.
    status = self.GetReportJob(report_job_id)[0]['reportJobStatus']
    while status != 'COMPLETED' and status != 'FAILED':
      if Utils.BoolTypeConvert(self._config['debug']):
        print 'Report job status: %s' % status
      time.sleep(30)
      status = self.GetReportJob(report_job_id)[0]['reportJobStatus']

    if status == 'FAILED':
      if Utils.BoolTypeConvert(self._config['debug']):
        print 'Report process failed'
      return ''
    else:
      if Utils.BoolTypeConvert(self._config['debug']):
        print 'Report has completed successfully'

    # Get report download URL.
    report_url = self.GetReportDownloadURL(report_job_id, export_format)[0]

    # Download report.
    data = urllib.urlopen(report_url).read()
    data = gzip.GzipFile(fileobj=StringIO.StringIO(data)).read()
    return data
    def DownloadXmlReport(self, report_job_id):
        """Download and return report data in XML format.

    Args:
      report_job_id: str ID of the report job.

    Returns:
      str Report data or None if report failed.
    """
        SanityCheck.ValidateTypes(((report_job_id, (str, unicode)), ))

        # Wait for report to finish.
        status = self.GetReportJobStatus(report_job_id)[0]
        while status != 'Completed' and status != 'Failed':
            if Utils.BoolTypeConvert(self._config['debug']):
                print 'Report job status: %s' % status
            time.sleep(30)
            status = self.GetReportJobStatus(report_job_id)[0]

        if status == 'Failed':
            if Utils.BoolTypeConvert(self._config['debug']):
                print 'Report process failed'
            return None

        if Utils.BoolTypeConvert(self._config['debug']):
            print 'Report has completed successfully'

        # Download report.
        report_url = self.GetGzipReportDownloadUrl(report_job_id)[0]

        # Convert report into readable XML format.
        report_xml = urllib.urlopen(report_url).read()
        return gzip.GzipFile(fileobj=StringIO.StringIO(report_xml)).read()
def GetServiceConnection(headers, config, url, http_proxy, is_jaxb_api):
    """Get SOAP service connection.

  Args:
    headers: dict Dictionary object with populated authentication
             credentials.
    config: dict Dictionary object with populated configuration values.
    url: str URL of the web service to call.
    http_proxy: str HTTP proxy to use.
    is_jaxb_api: bool Whether API uses JAXB.

  Returns:
    instance SOAPpy.SOAPProxy with set headers.
  """
    # Catch empty SOAP header elements and exclude them from request.
    full_headers = {}
    for key in headers:
        if headers[key]: full_headers[key] = headers[key]

    if is_jaxb_api or Utils.BoolTypeConvert(config['wsse']):
        headers = SOAPpy.Types.headerType(
            {config['ns_target'][1]: full_headers})
        headers._setAttr('xmlns', config['ns_target'][0])
        service = SOAPpy.SOAPProxy(url,
                                   http_proxy=http_proxy,
                                   header=headers,
                                   transport=HTTPTransportHandler)
        service.transport.data_injects = config['data_injects']
    elif Utils.BoolTypeConvert(config['force_data_inject']):
        service = SOAPpy.SOAPProxy(url,
                                   http_proxy=http_proxy,
                                   header=headers,
                                   transport=HTTPTransportHandler)
        service.transport.data_injects = config['data_injects']
    else:
        headers = SOAPpy.Types.headerType(full_headers)
        service = SOAPpy.SOAPProxy(url, http_proxy=http_proxy, header=headers)
    service.config.dumpHeadersIn = 1
    service.config.dumpHeadersOut = 1
    service.config.dumpSOAPIn = 1
    service.config.dumpSOAPOut = 1

    # Turn off type information, since SOAPpy usually gets the types wrong.
    service.config.typed = 0

    # Turn on noroot, to skip including "SOAP-ENC:root" as part of the request.
    service.noroot = 1

    # Explicitly set the style of the namespace, otherwise will default to 1999.
    service.config.namespaceStyle = '2001'

    # Set up OAuth, if applicable.
    if 'oauth_enabled' in config and config['oauth_enabled']:
        service.transport.oauth_enabled = True
        service.transport.oauth_handler = config['oauth_handler']
        service.transport.oauth_credentials = config['oauth_credentials']

    return service
Exemple #6
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 GetServiceConnection(headers, config, op_config, url, service_name, loc):
    """Get SOAP service connection.

  Args:
    headers: dict Dictionary object with populated authentication credentials.
    config: dict Dictionary object with populated configuration values.
    op_config: dict Dictionary object with additional configuration values for
               this operation.
    url: str URL of the web service to call.
    service_name: str API service name.
    loc: Service locator.

  Returns:
    instance of SoapBindingSOAP interface with set headers.
  """
    kw = {'tracefile': sys.stdout}
    use_conn_handler = False
    if Utils.BoolTypeConvert(config['raw_debug']):
        HttpConnectionHandler.debug = True
        HttpsConnectionHandler.debug = True
        use_conn_handler = True
    if Utils.BoolTypeConvert(config['compress']):
        HttpConnectionHandler.compress = True
        HttpsConnectionHandler.compress = True
        use_conn_handler = True
    if use_conn_handler and op_config['http_proxy']:
        HttpConnectionHandler.http_proxy = op_config['http_proxy']
        kw['transport'] = HttpConnectionHandler
    elif use_conn_handler:
        kw['transport'] = HttpsConnectionHandler

    if 'ns_target' in config: service_name += 'Service'
    port_type = eval('loc.get%sInterface(url=url, **kw)' % service_name)
    group = None
    if 'default_group' in op_config: group = op_config['default_group']
    port_type.binding.sig_handler = SigHandler(headers, config, group)

    # Set custom HTTP headers.
    postfix = ''
    if Utils.BoolTypeConvert(config['compress']): postfix = ', gzip'
    user_agent = 'ZSI %s%s' % ('.'.join(map(str, ZSI_VERSION)), postfix)
    port_type.binding.AddHeader('User-Agent', user_agent)

    # Handle OAuth (if enabled)
    if 'oauth_enabled' in config and config['oauth_enabled']:
        signedrequestparams = config[
            'oauth_handler'].GetSignedRequestParameters(
                config['oauth_credentials'], url)
        port_type.binding.AddHeader(
            'Authorization',
            'OAuth ' + config['oauth_handler'].FormatParametersForHeader(
                signedrequestparams))

    return port_type
    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, )
Exemple #9
0
    def __SetUseStrict(self, new_state):
        """Temporarily change strictness mode for a given AdWordsClient instance.

    Args:
      new_state: bool New state of the strictness mode.
    """
        self._config['strict'] = Utils.BoolTypeConvert(new_state, str)
Exemple #10
0
    def __SetRawDebug(self, new_state):
        """Temporarily change raw debug mode for a given AdWordsClient instance.

    Args:
      new_state: bool New state of the raw debug mode.
    """
        self._config['raw_debug'] = Utils.BoolTypeConvert(new_state, str)
Exemple #11
0
  def GetService(self, service_name, server='https://www.google.com',
                 version=None, http_proxy=None, op_config=None):
    """Generic method to create a service.

    Args:
      service_name: str Name of the service to create.
      [optional]
      server: str API server to access for API calls. The default value is
              'https://www.google.com'.
      version: str API version to use.
      http_proxy: str HTTP proxy to use.
      op_config: dict service configuration.

    Returns:
      GenericDfpService New object representing the SOAP service.
    """
    if version is None:
      version = DEFAULT_API_VERSION
    if Utils.BoolTypeConvert(self._config['strict']):
      DfpSanityCheck.ValidateServer(server, version)

    # Load additional configuration data.
    if op_config is None:
      op_config = {
          'server': server,
          'version': version,
          'http_proxy': http_proxy
      }
    return GenericDfpService(self._headers, self._config, op_config,
                             self.__lock, self.__logger, service_name)
Exemple #12
0
  def SetDebug(self, new_state):
    """Temporarily change debug mode for a given Client instance.

    Args:
      new_state: bool New state of the debug mode.
    """
    self._config['debug'] = Utils.BoolTypeConvert(new_state, str)
Exemple #13
0
  def __GenerateHeaders(self, return_micros):
    """Generates the headers to use for the report download.

    Args:
      return_micros: bool whether or not to use micros for money.

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

    # Handle OAuth (if enabled) and ClientLogin
    if self._headers.get('oauth2credentials'):
      self._headers['oauth2credentials'].apply(headers)
    else:
      headers['Authorization'] = ('GoogleLogin %s' %
          urllib.urlencode({'auth':
                            self._headers['authToken'].strip()}))

    headers['returnMoneyInMicros'] = str(return_micros).lower()
    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 #14
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 GetUserService(self, server='https://sandbox.google.com', version=None,
                     http_proxy=None):
    """Call API method in UserService.

    Args:
      [optional]
      server: str API server to access for this API call. Possible values
              are: 'https://www.google.com' for live site and
              'https://sandbox.google.com' for sandbox. The default behavior is
              to access sandbox site.
      version: str API version to use.
      http_proxy: str HTTP proxy to use.

    Returns:
      UserService New instance of UserService object.
    """
    headers = self._headers

    if version is None:
      version = MIN_API_VERSION
    if Utils.BoolTypeConvert(self._config['strict']):
      DfpSanityCheck.ValidateServer(server, version)

    # Load additional configuration data.
    op_config = {
      'server': server,
      'version': version,
      'http_proxy': http_proxy
    }
    return UserService(headers, self._config, op_config, self.__lock,
                       self.__logger)
  def _ReadyCompression(self):
    """Sets whether the HTTP transport layer should use compression.

    Overloaded for DFA because the DFA servers do not accept compressed
    messages. They do support returning compressed messages.
    """
    compress = Utils.BoolTypeConvert(self._config['compress'])
    self._soappyservice.soapproxy.config.send_compressed = False
    self._soappyservice.soapproxy.config.accept_compressed = compress
def main(client, order_id):
    # Initialize appropriate service.
    line_item_service = client.GetService('LineItemService', version='v201405')

    # Create statement object to only select line items with even delivery rates.
    values = [{
        'key': 'deliveryRateType',
        'value': {
            'xsi_type': 'TextValue',
            'value': 'EVENLY'
        }
    }, {
        'key': 'orderId',
        'value': {
            'xsi_type': 'NumberValue',
            'value': order_id
        }
    }]

    query = 'WHERE deliveryRateType = :deliveryRateType and orderId = :orderId'
    statement = DfpUtils.FilterStatement(query, values, 500)

    # Get line items by statement.
    response = line_item_service.GetLineItemsByStatement(
        statement.ToStatement())[0]

    line_items = response.get('results')

    if line_items:
        # Update each local line item by changing its delivery rate type.
        updated_line_items = []
        for line_item in line_items:
            if not Utils.BoolTypeConvert(line_item['isArchived']):
                line_item['deliveryRateType'] = 'AS_FAST_AS_POSSIBLE'
                updated_line_items.append(line_item)

        # Update line items remotely.
        line_items = line_item_service.UpdateLineItems(updated_line_items)

        # Display results.
        if line_items:
            for line_item in line_items:
                print(
                    'Line item with id \'%s\', belonging to order id \'%s\', named '
                    '\'%s\', and delivery rate \'%s\' was updated.' %
                    (line_item['id'], line_item['orderId'], line_item['name'],
                     line_item['deliveryRateType']))
        else:
            print 'No line items were updated.'
    else:
        print 'No line items found to update.'
  def DownloadMCCReport(self, report_definition_id, file_path=None,
                        return_micros=False, tries=50, sleep=30):
    """Blocking call to download a MCC report.

    This method will try to successfully download the report to the specified
    file_path, throwing an AdWordsApiError.  If file_path is None or not
    provided, will return as a string the downloaded report.

    Args:
      report_definition_id: str Id of the report definition to download.
      file_path: str File path to download to. Optional, returns string if None.
      return_micros: bool Whether to return currency in micros.
      tries: int Optional number of times to retry.
      sleep: int Optional number of seconds to sleep between retries.

    Returns:
      str Report data or a tuple of filename and bytes written if file_path is
      not None.

    Raises:
      AdWordsApiError: When we encounter a server error
    """
    response = self.GetMCCReportStatus(report_definition_id, return_micros,
                                       'new')
    while response['httpStatus'] != 301 and tries > 0:
      if response['httpStatus'] != 200:
        msg = []
        if 'state' in response: msg.append(response['state'])
        if 'failureReason' in response: msg.append(response['failureReason'])
        raise AdWordsApiError({
            'faultcode': '500',
            'faultstring': ' '.join(msg)})
      # Otherwise, it should be status == 200 which means try again later.
      if Utils.BoolTypeConvert(self._config['debug']):
        print 'Sleeping with %i tries left' % tries
      tries -= 1
      time.sleep(sleep)
      response = self.GetMCCReportStatus(report_definition_id, return_micros,
                                         response['queryToken'])
    if tries <= 0:
      raise AdWordsApiError({'faultstring': 'No more retries left.'})
    # On success, get the download URL from the Location header
    url = None
    if 'Location' in response['headers']:
      url = response['headers']['Location']
    else:
      url = response['headers']['location']
    headers = self.__GenerateHeaders(return_micros)
    return self.__DownloadFile(url, headers, file_path)
    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 #20
0
    def __init__(self,
                 client_id,
                 client_secret,
                 refresh_token,
                 mcc_cid,
                 dev_token,
                 debug=False):
        """Initializes an APIHandler.

    Args:
      client_id:
      client_secret:
      refresh_token:
      mcc_cid:
      dev_token:
      debug:
    """
        credentials = OAuth2Credentials(None, client_id, client_secret,
                                        refresh_token, None, self._REFRESH_URL,
                                        self._USER_AGENT)
        credentials.refresh(httplib2.Http())

        headers = {
            'clientCustomerId': mcc_cid,
            'userAgent': self._USER_AGENT,
            'developerToken': dev_token,
            'validateOnly': 'n',
            'partialFailure': 'n',
            'oauth2credentials': credentials
        }
        # App Engine doesn't allow you to write to the disk. Thus, we need to
        # explicitly turn off logging. Though, if debugging is enabled, the
        # data from STDOUT will be redirected to app engine's debugging console.
        # Note that we also specify that we want to use ElementTree here; see the
        # README for more information if you would rather use PyXML.
        config = {
            'debug': Utils.BoolTypeConvert(debug),
            'xml_log': 'n',
            'request_log': 'n',
            'pretty_xml': 'n',
            'xml_parser': '2',  # We're using ElementTree.
            'compress': 'n'
        }

        self.client = AdWordsClient(headers, config)
        self.client.use_mcc = True
Exemple #21
0
def main(client, order_id):
    # Initialize appropriate service.
    order_service = client.GetService('OrderService', version='v201408')

    # Create statement object to select a single order by an ID.
    values = [{
        'key': 'orderId',
        'value': {
            'xsi_type': 'NumberValue',
            'value': order_id
        }
    }]
    query = 'WHERE id = :orderId'

    statement = DfpUtils.FilterStatement(query, values)

    # Get orders by statement.
    response = order_service.GetOrdersByStatement(statement.ToStatement())[0]
    orders = response.get('results')

    if orders:
        # Update each local order object by changing its notes.
        updated_orders = []
        for order in orders:
            # Archived orders cannot be updated.
            if not Utils.BoolTypeConvert(order['isArchived']):
                order['notes'] = 'Spoke to advertiser. All is well.'
                updated_orders.append(order)

        # Update orders remotely.
        orders = order_service.UpdateOrders(updated_orders)

        # Display results.
        if orders:
            for order in orders:
                print(
                    'Order with id \'%s\', name \'%s\', advertiser id \'%s\', and '
                    'notes \'%s\' was updated.' %
                    (order['id'], order['name'], order['advertiserId'],
                     order['notes']))
        else:
            print 'No orders were updated.'
    else:
        print 'No orders found to update.'
Exemple #22
0
def main(client, ad_unit_id, team_id):
    # Initialize appropriate service.
    team_service = client.GetService('TeamService', version='v201408')

    # Create a filter statement to select a single team by ID.
    values = [{
        'key': 'teamId',
        'value': {
            'xsi_type': 'NumberValue',
            'value': team_id
        }
    }]
    query = 'WHERE id = :teamId'
    statement = DfpUtils.FilterStatement(query, values)

    # Get teams by statement.
    response = team_service.GetTeamsByStatement(statement.ToStatement())[0]
    teams = response.get('results')

    if teams:
        # Update each local team object by adding the ad unit to it.
        for team in teams:
            ad_unit_ids = []
            if 'adUnitIds' in team:
                ad_unit_ids = team['adUnitIds']
            # Don't add the ad unit if the team has all inventory already.
            if not Utils.BoolTypeConvert(team['hasAllInventory']):
                ad_unit_ids.append(ad_unit_id)
            team['adUnitIds'] = ad_unit_ids

        # Update teams on the server.
        teams = team_service.UpdateTeams(teams)

        # Display results.
        for team in teams:
            print('Team with id \'%s\' and name \'%s\' was updated.' %
                  (team['id'], team['name']))
    else:
        print 'No teams found to update.'
    def GetService(self,
                   service_name,
                   server='https://advertisersapi.doubleclick.net',
                   version=None,
                   http_proxy=None,
                   op_config=None):
        """Generic method to create a service.

    Args:
      service_name: str Name of the service to create.
      [optional]
      server: str API server this object will access. Possible values are:
              'https://advertisersapi.doubleclick.net' for production,
              'https://advertisersapitest.doubleclick.net' for test, and
              'https://betaadvertisersapi.doubleclick.net' for beta.
              The default behavior is to access the production environment.
      version: str API version to use.
      http_proxy: str HTTP proxy to use.
      op_config: dict Dictionary object with additional configuration values for
                 this operation.

    Returns:
      GenericDfaService New object representing the SOAP service.
    """
        if version is None:
            version = DEFAULT_API_VERSION
        if Utils.BoolTypeConvert(self._config['strict']):
            DfaSanityCheck.ValidateServer(server, version)

        # Load additional configuration data.
        if op_config is None:
            op_config = {
                'server': server,
                'version': version,
                'http_proxy': http_proxy
            }
        return GenericDfaService(self._headers, self._config, op_config,
                                 self.__lock, self.__logger, service_name)
  def GetService(self, service_name, server=DFP_SERVER,
                 version=None, http_proxy=None, op_config=None):
    """Generic method to create a service.

    Args:
      service_name: str Name of the service to create.
      [optional]
      server: str API server to access for API calls. The default value is
              'https://ads.google.com'.
      version: str API version to use.
      http_proxy: str HTTP proxy to use.
      op_config: dict service configuration.

    Returns:
      GenericDfpService New object representing the SOAP service.
    """
    if version is None:
      version = DEFAULT_API_VERSION

    if 'authToken' in self._headers and version > 'v201311':
      raise ApiVersionNotSupportedError('ClientLogin is not supported for '
                                        'version %s, please upgrade to '
                                        'OAuth2' % version)
    else:
      if Utils.BoolTypeConvert(self._config['strict']):
        DfpSanityCheck.ValidateServer(server, version)

      # Load additional configuration data.
      if op_config is None:
        op_config = {
            'server': server,
            'version': version,
            'http_proxy': http_proxy
        }
      return GenericDfpService(self._headers, self._config, op_config,
                               self.__lock, self.__logger, service_name)
    def __GenerateHeaders(self,
                          skip_report_header=None,
                          skip_report_summary=None):
        """Generates the headers to use for the report download.

    Args:
      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)})

        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 #26
0
# Initialize appropriate service. By default, the request is always made against
# the sandbox environment.
order_service = client.GetOrderService('https://sandbox.google.com', 'v201004')

# Create statement object to get all orders.
filter_statement = {'query': 'LIMIT 500'}

# Get orders by statement.
orders = order_service.GetOrdersByStatement(filter_statement)[0]['results']

if orders:
    # Update each local order object by changing its notes.
    updated_orders = []
    for order in orders:
        # Archived orders cannot be updated.
        if not Utils.BoolTypeConvert(order['isArchived']):
            order['notes'] = 'Spoke to advertiser. All is well.'
            updated_orders.append(order)

    # Update orders remotely.
    orders = order_service.UpdateOrders(updated_orders)

    # Display results.
    if orders:
        for order in orders:
            print(
                'Order with id \'%s\', name \'%s\', advertiser id \'%s\', and '
                'notes \'%s\' was updated.' %
                (order['id'], order['name'], order['advertiserId'],
                 order['notes']))
    else:
  def __init__(self, headers=None, config=None, path=None):
    """Inits Client.

    Args:
      [optional]
      headers: dict Object with populated authentication credentials.
      config: dict Object with client configuration values.
      path: str Relative or absolute path to home directory (i.e. location of
            pickles and logs/).

    Example:
      headers = {
        'email': '*****@*****.**',
        'password': '******',
        'authToken': '...',
        'applicationName': 'GoogleTest',
        'networkCode': 'ca-01234567',
        'oauth2credentials': 'See use_oauth2.py'
      }
      config = {
        'home': '/path/to/home',
        'log_home': '/path/to/logs/home',
        'proxy': 'http://example.com:8080',
        'xml_parser': '1', # PYXML = 1, ELEMENTREE = 2
        'debug': 'n',
        'raw_debug': 'n',
        'xml_log': 'y',
        'request_log': 'y',
        'raw_response': 'n',
        'strict': 'y',
        'pretty_xml': 'y',
        'compress': 'y',
        'access': ''
      }
      path = '/path/to/home'
    """
    super(DfpClient, self).__init__(headers, config, path)

    self.__lock = thread.allocate_lock()
    self.__loc = None

    if path is not None:
      # Update absolute path for a given instance of DfpClient, based on
      # provided relative path.
      if os.path.isabs(path):
        DfpClient.home = path
      else:
        # NOTE(api.sgrinberg): Keep first parameter of join() as os.getcwd(),
        # do not change it to DfpClient.home. Otherwise, may break when
        # multiple instances of DfpClient exist during program run.
        DfpClient.home = os.path.join(os.getcwd(), path)

      # If pickles don't exist at given location, default to "~".
      if (not headers and not config and
          (not os.path.exists(os.path.join(DfpClient.home,
                                           DfpClient.auth_pkl_name)) or
           not os.path.exists(os.path.join(DfpClient.home,
                                           DfpClient.config_pkl_name)))):
        DfpClient.home = os.path.expanduser('~')
    elif not headers:
      DfpClient.home = os.path.expanduser('~')

    # Update location for both pickles.
    DfpClient.auth_pkl = os.path.join(DfpClient.home,
                                      DfpClient.auth_pkl_name)
    DfpClient.config_pkl = os.path.join(DfpClient.home,
                                        DfpClient.config_pkl_name)

    # Only load from the pickle if config wasn't specified.
    self._config = config or self.__LoadConfigValues()
    self._config = self.__SetMissingDefaultConfigValues(self._config)
    self._config['home'] = DfpClient.home

    # Validate XML parser to use.
    SanityCheck.ValidateConfigXmlParser(self._config['xml_parser'])

    # Only load from the pickle if 'headers' wasn't specified.
    if headers is None:
      self._headers = self.__LoadAuthCredentials()
    else:
      if Utils.BoolTypeConvert(self._config['strict']):
        SanityCheck.ValidateRequiredHeaders(headers, REQUIRED_SOAP_HEADERS)
      self._headers = headers

    # Load/set authentication token.
    try:
      if headers and 'authToken' in headers and headers['authToken']:
        self._headers['authToken'] = headers['authToken']
      elif 'email' in self._headers and 'password' in self._headers:
        self._headers['authToken'] = Utils.GetAuthToken(
            self._headers['email'], self._headers['password'],
            AUTH_TOKEN_SERVICE, LIB_SIG, self._config['proxy'])
      elif (self._headers.get('oauth2credentials')):
        # If they have oauth2credentials, that's also fine.
        pass
      else:
        msg = ('Authentication data, email or/and password, OAuth2 credentials '
               'is missing.')
        raise ValidationError(msg)
      self._config['auth_token_epoch'] = time.time()
    except AuthTokenError:
      # We would end up here if non-valid Google Account's credentials were
      # specified.
      self._headers['authToken'] = None
      self._config['auth_token_epoch'] = 0

    # Initialize logger.
    self.__logger = Logger(LIB_SIG, self._config['log_home'])
    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
Exemple #29
0
filter_statement = {'query': 'WHERE id > 0 LIMIT 5'}

# Get teams by statement.
response = team_service.GetTeamsByStatement(filter_statement)[0]
teams = []
if 'results' in response:
    teams = response['results']

if teams:
    # Update each local team object by adding the ad unit to it.
    for team in teams:
        ad_unit_ids = []
        if 'adUnitIds' in team:
            ad_unit_ids = team['adUnitIds']
        # Don't add the ad unit if the team has all inventory already.
        if not Utils.BoolTypeConvert(team['hasAllInventory']):
            ad_unit_ids.append(ad_unit_id)
        team['adUnitIds'] = ad_unit_ids

    # Update teams on the server.
    teams = team_service.UpdateTeams(teams)

    # Display results.
    if teams:
        for team in teams:
            print('Team with id \'%s\' and name \'%s\' was updated.' %
                  (team['id'], team['name']))
    else:
        print 'No teams were updated.'
else:
    print 'No teams found to update.'
}]
filter_statement = {'query': 'WHERE deliveryRateType = :deliveryRateType and '
                    'orderId = :orderId LIMIT 500',
                    'values': values}

# Get line items by statement.
response = line_item_service.GetLineItemsByStatement(filter_statement)[0]
line_items = []
if 'results' in response:
  line_items = response['results']

if line_items:
  # Update each local line item by changing its delivery rate type.
  updated_line_items = []
  for line_item in line_items:
    if not Utils.BoolTypeConvert(line_item['isArchived']):
      line_item['deliveryRateType'] = 'AS_FAST_AS_POSSIBLE'
      updated_line_items.append(line_item)

  # Update line items remotely.
  line_items = line_item_service.UpdateLineItems(updated_line_items)

  # Display results.
  if line_items:
    for line_item in line_items:
      print ('Line item with id \'%s\', belonging to order id \'%s\', named '
             '\'%s\', and delivery rate \'%s\' was updated.'
             % (line_item['id'], line_item['orderId'], line_item['name'],
                line_item['deliveryRateType']))
  else:
    print 'No line items were updated.'