Giter Site home page Giter Site logo

googleads-python-lib's Introduction

The Google Ad Manager SOAP API Python client library

This client library simplifies accessing the Google Ad Manager SOAP API. The library provides easy ways to store your authentication and create SOAP web service clients. It also contains example code to help you get started integrating with our APIs.

Getting started

  1. Download and install the library

    setuptools is a pre-requisite for installing the googleads library

    It is recommended that you install the library and its dependencies from PyPI using pip. This can be accomplished with a single command:

    $ pip install googleads

    As an alternative, you can download the library as a tarball. To start the installation, navigate to the directory that contains your downloaded unzipped client library and run the "setup.py" script as follows:

    $ python setup.py build install

  2. Copy the googleads.yaml file to your home directory.

    This will be used to store credentials and other settings that can be loaded to initialize a client.

  3. Set up your OAuth2 credentials

    The Ad Manager API uses OAuth2 as the authentication

  4. mechanism. Follow the appropriate guide below based on your use case.

    If you're accessing an API using your own credentials...

    If you're accessing an API on behalf of clients...

Where can I find samples?

You can find code examples for the latest versions of Ad Manager on the releases page.

Alternatively, you can find Ad Manager samples in the examples directory of this repository.

Caching authentication information

It is possible to cache your API authentication information. The library includes a sample file showing how to do this named googleads.yaml. Fill in the fields for the API and features you plan to use. The library's LoadFromStorage methods default to looking for a file with this name in your home directory, but you can pass in a path to any file with the correct yaml contents.

# Use the default location - your home directory:
ad_manager_client = ad_manager.AdManagerClient.LoadFromStorage()

# Alternatively, pass in the location of the file:
ad_manager_client = ad_manager.AdManagerClient.LoadFromStorage('C:\My\Directory\googleads.yaml')

Where do I submit bug reports and/or feature requests?

If you have issues directly related to the client library, use the issue tracker.

If you have issues pertaining to a specific API, use the product support forums:

How do I log SOAP interactions?

The library uses Python's built in logging framework. You can specify your configuration via the configuration file; see googleads.yaml for an example.

Alternatively, you can manually specify your logging configuration. For example, if you want to log your SOAP interactions to stdout, and you are using the Zeep soap library, you can do the following:

logging.basicConfig(level=logging.INFO, format=googleads.util.LOGGER_FORMAT)
logging.getLogger('googleads.soap').setLevel(logging.DEBUG)

If you wish to log to a file, you'll need to attach a log handler to this source which is configured to write the output to a file.

How do I disable log filters?

The zeep plugin used for logging strips sensitive data from its output. If you would like this data included in logs, you'll need to implement your own simple logging plugin. For example:

class DangerousZeepLogger(zeep.Plugin):
  def ingress(self, envelope, http_headers, operation):
    logging.debug('Incoming response: \n%s', etree.tostring(envelope, pretty_print=True))
    return envelope, http_headers

  def egress(self, envelope, http_headers, operation, binding_options):
    logging.debug('Incoming response: \n%s', etree.tostring(envelope, pretty_print=True))
    return envelope, http_headers

ad_manager_client.zeep_client.plugins.append(DangerousZeepLogger())

How can I configure or disable caching?

By default, clients are cached because reading and digesting the WSDL can be expensive. However, the default caching method requires permission to access a local file system that may not be available in certain hosting environments such as App Engine.

You can pass an implementation of zeep.cache.Base to the AdManagerClient initializer to modify the default caching behavior.

For example, configuring a different location and duration of the cache file with zeep

doc_cache = zeep.cache.SqliteCache(path=cache_path)
ad_manager_client = ad_manager.AdManagerClient(
  oauth2_client, application_name, network_code=network_code, cache=doc_cache)

You can also disable caching in similar fashion with zeep

ad_manager_client = ad_manager.AdManagerClient(
  oauth2_client, application_name, network_code=network_code,
  cache=googleads.common.ZeepServiceProxy.NO_CACHE)

Requirements

Python Versions

This library only supports Python 3.7+.

External Dependencies:

- httplib2             -- https://pypi.python.org/pypi/httplib2/
- oauth2client         -- https://pypi.python.org/pypi/oauth2client/
- pysocks              -- https://pypi.python.org/pypi/PySocks/
- pytz                 -- https://pypi.python.org/pypi/pytz
- pyYAML               -- https://pypi.python.org/pypi/pyYAML/
- xmltodict            -- https://pypi.python.org/pypi/xmltodict/
- zeep                 -- https://pypi.python.org/pypi/zeep
- mock                 -- https://pypi.python.org/pypi/mock
                          (only needed to run unit tests)
- pyfakefs             -- https://pypi.python.org/pypi/pyfakefs
                          (only needed to run unit tests)

Authors:

Mark Saniscalchi
David Wihl
Ben Karl

googleads-python-lib's People

Contributors

andreferraro avatar benkarl avatar benrkarl avatar grivescorbett avatar jdilallo avatar jonathasreuel avatar lsv1 avatar manuelaf avatar mpaolino avatar msaniscalchi avatar ncouture avatar nicholaschen avatar rcotrina94 avatar sahilkukreja avatar thangduo avatar wihl avatar xzkostyan avatar yufengg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

googleads-python-lib's Issues

removing criteria breaks if shared set is empty + solutions

For googleads-python-lib/examples/adwords/v201502/advanced_operations/find_and_remove_criteria_from_shared_set.py
The code provided currently breaks if it encounters a negative shared set of keywords that is empty, with no keywords or placements.
This may or may not be a deliberate design decision to crash the program if it encounters a shared set that has no keywords or placements.
But for people who are using this code for more than just finding and removing criteria and/or people who wouldn't like their code to stop as soon as it encounters an empty shared sets, I have some fixes/workarounds for this behavior (that don't involve try).

There are two reasons that this code throws errors and breaks when it encounters an empty shared set. For each of the reasons, I have provided, solutions and/or workarounds to these problems, the probable cause of the program-stopping errors, as well as the error output.

Exhibit A:
Problem:
When the code sets the initial values to look for criteria (line108), it sets totalNumEntries to be 1 in page. This gets it into get into the loop looking at the result of page = shared_criterion_service.get(selector) (line 111) and then tries to look at page['entries'], where it then crashes, because page doesn't have 'entries' because the shared set it is looking at has no entries.
error:
Printed below is the page(with a print page statement) for an empty shared set and the error that the code throws:
(SharedCriterionPage){
totalNumEntries = 0
Page.Type = "SharedCriterionPage"
}
Traceback (most recent call last):
File "test6_add_gen_neg_keywords.py", line 423, in
newly_visited_shared_sets = main(adwords_client, campaign[0], visited_shared_sets, shared_set_table)
File "test6_add_gen_neg_keywords.py", line 164, in main
if page['entries']:
File "/opt/devel/lib/python2.7/site-packages/suds/sudsobject.py", line 154, in getitem
return getattr(self, name)
AttributeError: 'SharedCriterionPage' object has no attribute 'entries'
Solution:
One solution (that I've implemented) is to check that the totalNumEntries is still more than 0 before trying to access page['entries'] in the line if page['entries']:
if page['totalNumEntries'] > offset:
if page['entries']:
Another potential solution that I haven't tested is, instead of writing
if page['entries']:
at line 112 instead write
if 'entries' in page:
as written in line 79 of this code, since that page query doesn't break if a campaign doesn't have shared sets so this syntax seems to work.

Exhibit B:
Problem:
The code breaks at response = shared_criterion_service.mutate(operations) (line 145)
if the operations doesn't have any criterion_ids to work on, aka if criterion_ids is an empty list. I don't know why asking it to remove nothing breaks it, but I do have a solution.
Error:
Printed below is the page for an empty shared set and the error given when trying to run this program
(SharedCriterionPage){
totalNumEntries = 0
Page.Type = "SharedCriterionPage"
}
2015-06-23 13:40:08 suds.client ERROR <suds.sax.document.Document instance at 0x1232ab8>
Traceback (most recent call last):
File "test6_add_gen_neg_keywords.py", line 423, in
newly_visited_shared_sets = main(adwords_client, campaign[0], visited_shared_sets, shared_set_table)
File "test6_add_gen_neg_keywords.py", line 205, in main
response = shared_criterion_service.mutate(operations)
File "/opt/devel/lib/python2.7/site-packages/googleads/common.py", line 296, in MakeSoapRequest
for arg in args])
File "/opt/devel/lib/python2.7/site-packages/suds/client.py", line 521, in call
return client.invoke(args, kwargs)
File "/opt/devel/lib/python2.7/site-packages/suds/client.py", line 581, in invoke
result = self.send(soapenv)
File "/opt/devel/lib/python2.7/site-packages/suds/client.py", line 619, in send
description=tostr(e), original_soapenv=original_soapenv)
File "/opt/devel/lib/python2.7/site-packages/suds/client.py", line 670, in process_reply
raise WebFault(fault, replyroot)
suds.WebFault: Server raised fault: '[NotEmptyError.EMPTY_LIST @ operations]'
Solution:
You do not need to do the remove operation, or request a response for it if there are no criterion_ids to remove
Therefore, I placed the block of code responsible for removing criterion and reporting on it in an if clause in order to check if there are any criterion_ids to remove before trying to remove any criteria
if criterion_ids:
block of code for removing and reporting on criterions (lines134-151)

I hoped that helped you!

estimate_keyword_traffic.py is not running

Getting this exception with the new release -

Traceback (most recent call last):
File "estimate_keyword_traffic.py", line 122, in
main(adwords_client)
File "estimate_keyword_traffic.py", line 37, in main
'TrafficEstimatorService', version='v201409')
File "/Library/Python/2.7/site-packages/googleads/adwords.py", line 261, in GetService
'Supported versions: %s' % (version, _SERVICE_MAP.keys()))
googleads.errors.GoogleAdsValueError: Unrecognized version of the AdWords API. Version given: v201409 Supported versions: ['v201402', 'v201406']

Issues reading non ascii characters

Hi there

somehow I have problems pasing non- ascii characters via the python lib to Adwords API, i.e. every time I try to request / send keyword information for non ascii characters (Chinese, Japanese, Rusian, Latin, to name a few) I get the following error 'UnicodeDecodeError: 'ascii' codec can't decode byte...'
Please note I am following the pep-0263 instructions to handle UTF8 decoding

ImportError: No module named ZSI

After installing the client on windows 7 any of the examples return error about the import of the ZSI module. Is there anything else needed to be done except the following command?

setup.py build install

This is the error:

C:\yPart\TempDir\adwords_api_python_14.2.4\examples\adspygoogle\adwords\v201101>get_all_campaigns
.py
Traceback (most recent call last):
File "C:\yPart\TempDir\adwords_api_python_14.2.4\examples\adspygoogle\adwords\v201101\get_all_c
ampaigns.py", line 37, in
'https://adwords-sandbox.google.com', 'v201101')
File "........\adspygoogle\adwords\AdWordsClient.py", line 848, in GetCampaignService
self.logger)
File "........\adspygoogle\adwords\CampaignService.py", line 60, in __init

headers, config, op_config, url, 'adspygoogle.adwords', lock, logger)
File "........\adspygoogle\common\ApiService.py", line 88, in init
raise ImportError(e)
ImportError: No module named ZSI

Error using python lib for dfp

Hi All,

I installed python client library 1.0.3 from https://github.com/googleads/googleads-python-lib/releases on my Linux box (Linux 2.6.32-279.el6.x86_64 x86_64) and I did not get any error. I gave all the required information in googleads.yaml file also.

When I run any example let’s say ‘get_all_companies.py’ in Company Service, I get below error always:
dfp_client = dfp.DfpClient.LoadFromStorage()

Traceback (most recent call last):
File "./get_all_companies.py", line 60, in
dfp_client = dfp.DfpClient.LoadFromStorage(path=os.path.join(os.path.expanduser('~'), 'googleads.yaml'))
File "build/bdist.linux-x86_64/egg/googleads/dfp.py", line 107, in LoadFromStorage
File "build/bdist.linux-x86_64/egg/googleads/common.py", line 83, in LoadFromStorage
AttributeError: 'str' object has no attribute 'keys'

Also when i give complete path as below:

dfp_client = dfp.DfpClient.LoadFromStorage('/home/Kapil.kumar/googleads/googleads.yaml')
Traceback (most recent call last):
File "./get_all_companies.py", line 61, in
dfp_client = dfp.DfpClient.LoadFromStorage('/home/kapil.kumar/sos_code/DFP/googleads-python-lib-master/googleads.yaml')
File "build/bdist.linux-x86_64/egg/googleads/dfp.py", line 107, in LoadFromStorage
File "build/bdist.linux-x86_64/egg/googleads/common.py", line 83, in LoadFromStorage
AttributeError: 'str' object has no attribute 'keys'

Please help and let me know what i am missing. Any help is appreciated.

Thanks,
Kapil

ProductPartition example does not work.

I'm using the example found in examples/adwords/v201402/shopping/add_product_partition_tree.py

WebFault: Server raised fault: '[InternalApiError.UNEXPECTED_INTERNAL_API_ERROR @ com.google.ads.api.services.common.error.InternalApiError.(InternalApiErro]' is raised

I'm using MCC test account if that matters.

Migration issues

Hi!

There are few issues when migrating to this lib that are currently not addressed. Mainly two things:

  • Lack of error exceptions. The user application must parse the error objects itself and also establish its own exception hierarchy. It cannot rely on approriate exceptions being raised by the client lib. The previous lib (adspygoogle) partly did this, however a lot of clients would benefit when the error-string -> exception mapping would happen in the lib.
  • OAuth error handling is missing. When the attempt to retrieve an access token from a refresh token fails then the lib currently silently omits the Authorization header, leading to LOGIN_COOKIE_REQUIRED api errors. OAuth error handling should be extended. Additionally it may be helpful to also allow giving access tokens to the client in order to enable reusing access tokens within their life time.

Is anybody currently working on a new set of related feature for the lib or should we start submitting patches?

Example code with wrong variable name

In your example code you have...

    # Display results.
    print 'Report job with id \'%s\' downloaded to:\n%s' % (
        report_job['id'], report_file.name)

However there is no report_job['id'] variable which causes a traceback report. I think you meant to write report_job_id instead. I'm not sure how many examples this is prevalent in.

Adwords v201502 services

I noticed that the news services aren't added yet. please update the list to v201502

this is the new list

'v201502': {
'AccountLabelService': 'mcm',
'AdCustomizerFeedService': 'cm',
'AdGroupAdService': 'cm',
'AdGroupBidModifierService': 'cm',
'AdGroupCriterionService': 'cm',
'AdGroupExtensionSettingService': 'cm',
'AdGroupFeedService': 'cm',
'AdGroupService': 'cm',
'AdParamService': 'cm',
'AdwordsUserListService': 'rm',
'BiddingStrategyService': 'cm',
'BudgetOrderService': 'billing',
'BudgetService': 'cm',
'CampaignAdExtensionService': 'cm',
'CampaignCriterionService': 'cm',
'CampaignFeedService': 'cm',
'CampaignService': 'cm',
'CampaignSharedSetService': 'cm',
'ConstantDataService': 'cm',
'ConversionTrackerService': 'cm',
'CustomerExtensionSettingService': 'cm',
'CustomerFeedService': 'cm',
'CustomerService': 'mcm',
'CustomerSyncService': 'ch',
'DataService': 'cm',
'ExperimentService': 'cm',
'FeedItemService': 'cm',
'FeedMappingService': 'cm',
'FeedService': 'cm',
'GeoLocationService': 'cm',
'LabelService': 'cm',
'LocationCriterionService': 'cm',
'ManagedCustomerService': 'mcm',
'MediaService': 'cm',
'MutateJobService': 'cm',
'OfflineConversionFeedService': 'cm',
'ReportDefinitionService': 'cm',
'SharedCriterionService': 'cm',
'SharedSetService': 'cm',
'TargetingIdeaService': 'o',
'TrafficEstimatorService': 'o',
},

No Campaigns Found

Hi,

I am a newbie to this library. I was able to set up the googleads.yaml file using the generate_refresh_token.py. However everytime I run "python get_campaigns.py" I get "No Campaigns were found".

I know that there are campaigns in the account. Is there something that I am doing wrong ?

Thanks

Unrecognizeed service using: add_site_links.py

when i use the CampaignExtensionSettingService in version 201409
( https://raw.githubusercontent.com/googleads/googleads-python-lib/master/examples/adwords/v201409/extensions/add_site_links.py )
I get the error:


GoogleAdsValueError: Unrecognized service for the AdWords API. Service given: CampaignExtensionSettingService Supported services: 
['BudgetOrderService', 'MediaService', 'CampaignAdExtensionService', 'CampaignService', 'ConversionTrackerService', 'FeedMappingService', 
'SharedSetService', 'AdGroupService', 'AdGroupCriterionService', 'AdGroupBidModifierService', 'ReportDefinitionService', 
'DataService', 'LocationCriterionService', 'OfflineConversionFeedService', 'AdGroupAdService', 'BiddingStrategyService', 
'ExperimentService', 'LabelService', 'FeedItemService', 'AdwordsUserListService', 'GeoLocationService', 'CampaignFeedService', 
'CustomerSyncService', 'CustomerService', 'ManagedCustomerService', 'AdGroupFeedService', 'FeedService', 'BudgetService', 
'CampaignSharedSetService', 'ConstantDataService', 'CampaignCriterionService', 'TargetingIdeaService', 'SharedCriterionService', 
'MutateJobService', 'AdParamService', 'CustomerFeedService', 'TrafficEstimatorService']  

GoogleRefreshTokenClient doesn't seem to correctly refresh a token after an hour of usage

The following exception is raised after one hour (which, as far as I know is the expiration time on access tokens.)

Traceback (most recent call last):
  File "", line 118, in <module>
    sys.exit(main(**kwargs))
  File "cli.py", line 415, in main
    dry_run=dry_run
  File "entities.py", line 261, in commit
    self.push_to_google(chunk, settings)
  File "entities.py", line 291, in push_to_google
    response = f(mutations, settings)
  File "entities.py", line 401, in mutate
    return service.mutate(mutations)
  File "client.py", line 60, in mutate
    retval = self.service.mutate(mutations)
  File "/Library/Python/2.7/site-packages/googleads/common.py", line
231, in MakeSoapRequest
    for arg in args])
  File "/Library/Python/2.7/site-packages/suds/client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "/Library/Python/2.7/site-packages/suds/client.py", line 581, in invoke
    result = self.send(soapenv)
  File "/Library/Python/2.7/site-packages/suds/client.py", line 619, in send
    description=tostr(e), original_soapenv=original_soapenv)
  File "/Library/Python/2.7/site-packages/suds/client.py", line 670,
in process_reply
    raise WebFault(fault, replyroot)
suds.WebFault: Server raised fault:
'[AuthenticationError.OAUTH_TOKEN_INVALID @ ; trigger:'<null>']'

A GoogleRefreshtTokenClient instance was created with:

auth2_client = GoogleRefreshTokenClient(creds['client_id'],
                                        creds['client_secret'],
                                        creds['token']['refresh_token'])

This is running on Python 2.7, with the following package versions:

googleads==2.0.1
httplib2==0.9
oauthlib==0.6.3
suds-jurko==0.6

The script is trying to run a large set of mutations against the API, it runs ok for exactly an hour each time, then it raises this error.

Library picking incorrect encoder?

I have the code:

report_downloader = client.GetReportDownloader(version='v201409')
report_query = ('SELECT Impressions,QualityScore,KeywordText ' +
                'FROM KEYWORDS_PERFORMANCE_REPORT ' +
                'WHERE Impressions > 0 ' +
                'DURING YESTERDAY ')
r = report_downloader.DownloadReportAsStringWithAwql(report_query, 'CSV').splitlines()

And I get the exception:

Traceback (most recent call last):
  File "qs_tracking.py", line 100, in <module>
    qs_report(list_of_customer_ids, tracking_config)
  File "qs_tracking.py", line 68, in qs_report
    r = qs_report_one_acc(client)
  File "qs_tracking.py", line 34, in qs_report_one_acc
    r = report_downloader.DownloadReportAsStringWithAwql(report_query, 'CSV').splitlines()
  File "/usr/local/lib/python2.7/dist-packages/googleads/adwords.py", line 635, in DownloadReportAsStringWithAwql
    return response.read().decode()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 55408: ordinal not in range(128)

This only happens in one of my accounts. In the others this code runs fine.

Issue when upgrading from 2.0.2 to 3.2.0

Hi,

I am trying to upgrade a few DFP services and have this below issue. I am using a python 2.6.9 install with a virtual environment one for each 2.0.2 and 3.2.0 . I am behind a proxy and that is configured in the yaml file.(Please note credentials are hashed but i know they work for sure with the old library and a newer API version like v210502)
------------------------------------ Error -----
(venv)[pyve320]$ python test_dfp_access.py
https://xxx.xx.xx.xx:xxxx
Traceback (most recent call last):
File "test_dfp_access.py", line 18, in
response = order_service.getOrdersByStatement(statement.ToStatement())
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/googleads/common.py", line 294, in MakeSoapRequest
self._header_handler.SetHeaders(self.suds_client)
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/googleads/dfp.py", line 316, in SetHeaders
headers=self._dfp_client.oauth2_client.CreateHttpHeader())
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/googleads/oauth2.py", line 150, in CreateHttpHeader
self.Refresh()
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/googleads/oauth2.py", line 166, in Refresh
self.disable_ssl_certificate_validation)))
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/oauth2client/client.py", line 577, in refresh
self._refresh(http.request)
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/oauth2client/client.py", line 748, in _refresh
self._do_refresh_request(http_request)
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/oauth2client/client.py", line 777, in _do_refresh_request
self.token_uri, method='POST', body=body, headers=headers)
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/httplib2/init.py", line 1593, in request
(response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/httplib2/init.py", line 1335, in _request
(response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/u01/processes/dev2/tst_env/pyve320/venv/lib/python2.6/site-packages/httplib2/init.py", line 1263, in _conn_request
raise ServerNotFoundError("Unable to find the server at %s" % conn.host)
httplib2.ServerNotFoundError: Unable to find the server at accounts.google.com
(venv)[pyve320]$
--------------------------------------------- Python Packages
PySocks==1.5.0
PyYAML==3.11
googleads==3.2.0
httplib2==0.9
oauth2client==1.4.7
pyasn1==0.1.7
pyasn1-modules==0.0.5
pytz==2014.10
rsa==3.1.4
six==1.9.0
suds-jurko==0.6
---------------------------------------------googleads.yaml---
adwords:
developer_token: INSERT_DEVELOPER_TOKEN_HERE
user_agent: INSERT_USER_AGENT_HERE
client_id: INSERT_OAUTH_2_CLIENT_ID_HERE
client_secret: INSERT_CLIENT_SECRET_HERE
refresh_token: INSERT_REFRESH_TOKEN_HERE
# The following values are optional:
# client_customer_id: INSERT_CLIENT_CUSTOMER_ID_HERE
# partial_failure: True
# validate_only: True

dfp:
application_name: DFPRreporting
client_id: 999999999999-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com
client_secret: vvvvvvvvvvvv-lllll-1111
refresh_token: 7/888888888888888888888888888888888888-rttttt
# The following values are optional:
network_code: 1111

dfa:
username: INSERT_DFA_USERNAME_HERE
application_name: INSERT_APPLICATION_NAME_HERE
client_id: INSERT_OAUTH_2_CLIENT_ID_HERE
client_secret: INSERT_CLIENT_SECRET_HERE
refresh_token: INSERT_REFRESH_TOKEN_HERE
# The following values are optional:

# The following are optional settings for using a proxy.
proxy_info:
host: https://xxx.xx.xx.xx
port: yyyy
# The following values are optional:
# disable_ssl_certificate_validation: False
# ca_certs: INSERT_PATH_HERE
----------------------------------Test Python Script ---
import googleads
from googleads import dfp
dfp_client = dfp.DfpClient.LoadFromStorage('googleads.yaml')

client = dfp_client
#print(client)
print(client.https_proxy)
order_id = '123456789'
order_service = client.GetService('OrderService', version='v201502')
#print(order_service.suds_client)

# 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 = dfp.FilterStatement(query, values)

response = order_service.getOrdersByStatement(statement.ToStatement())

orders = []
if 'results' in response:
orders = response['results']

# Display results.
for order in orders:
print ('Order with id '%s' name '%s' was found.'
% (order['id'], order['name']))

print '\nNumber of results found: %s' % len(orders)

print('Success')

ReportDownloader: Problem with downloading report in binary format

The public function DownloadReportWithAwql checks binary format of a file object ('wb') protocol and it is not compatible with binary buffers.

As a workaround I am using the private function_DownloadReport

buffer_ = StringIO() if report_format == 'CSV' else BytesIO()
downloader._DownloadReport(downloader._SerializeAwql(query, report_format),
                                       buffer_,return_money_in_micros,skip_report_header,skip_report_summary)

The downloaded data seems fine, I am not sure though this is the desired interface.

get_all_ad_units.py fails when run after create_ad_units.py

Hi,

From the inventory_service examples, I ran the "get_all_ad_units.py" to get all the ad units and their Ids. I used the parent Id from this output to run "create_ad_units.py" and successfully create two Ad Units under our Test account. However, when I subsequently ran the "get_all_ad_units.py" after running the "create_ad_units.py", I received this error: "suds.WebFault: Server raised fault: '[ServerError.SERVER_ERROR @ ]'".

The same "get_all_ad_units.py" program runs fine when run against our production dfp account, on which "create_ad_units.py" was not run.

suds_error

Decode error in ReportDownloader

I'm trying to download a report using the ReportDownloader and get the following trace:

  File "/usr/local/lib/python2.7/dist-packages/googleads/adwords.py", line 348, in DownloadReport
    output, return_money_in_micros)
  File "/usr/local/lib/python2.7/dist-packages/googleads/adwords.py", line 411, in _DownloadReport
    output.write(chunk.decode())
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 147: ordinal not in range(128)

Looks like the ReportDownloader is trying to decode some non-ascii chars.

ValueError: AbstractBasicAuthHandler does not support the following scheme: 'OAuth'

I'm trying to download account information using the CustomerServices' get method, but I get the following stacktrace:

Traceback (most recent call last):
  File "tasks.py", line 762, in download_and_link_adwords_accounts
    accounts = download_user_adwords_accounts(user_id, google_sub)
  File "/venv/lib/python3.4/site-packages/celery/local.py", line 167, in <lambda>
    __call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw)
  File "/venv/lib/python3.4/site-packages/celery/app/trace.py", line 417, in __protected_call__
    return orig(self, *args, **kwargs)
  File "/venv/lib/python3.4/site-packages/celery/app/task.py", line 420, in __call__
    return self.run(*args, **kwargs)
  File "tasks.py", line 729, in download_user_adwords_accounts
    mcc.account)
  File "tasks.py", line 316, in download_adwords_accounts
    customer_info = customer_service.get()
  File "/venv/lib/python3.4/site-packages/googleads/common.py", line 231, in MakeSoapRequest
    for arg in args])
  File "/venv/lib/python3.4/site-packages/suds/client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "/venv/lib/python3.4/site-packages/suds/client.py", line 581, in invoke
    result = self.send(soapenv)
  File "/venv/lib/python3.4/site-packages/suds/client.py", line 613, in send
    reply = self.options.transport.send(request)
  File "/venv/lib/python3.4/site-packages/suds/transport/https.py", line 66, in send
    return HttpTransport.send(self, request)
  File "/venv/lib/python3.4/site-packages/suds/transport/http.py", line 82, in send
    fp = self.u2open(u2request)
  File "/venv/lib/python3.4/site-packages/suds/transport/http.py", line 132, in u2open
    return url.open(u2request, timeout=tm)
  File "/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 461, in open
    response = meth(req, response)
  File "/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 571, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 493, in error
    result = self._call_chain(*args)
  File "/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 433, in _call_chain
    result = func(*args)
  File "/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 906, in http_error_401
    url, req, headers)
  File "/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 872, in http_error_auth_reqed
    scheme)
ValueError: AbstractBasicAuthHandler does not support the following scheme: 'OAuth'

The following code produces the error:

oauth2_client = GoogleRefreshTokenClient(client_id, client_secret, refresh_token)
client = AdWordsClient(adwords_developer_token, oauth2_client, 'User Agent')
customer_service = client.GetService('CustomerService', version='v201402')
customer_info = customer_service.get()

I put suds into debug mode and ran the code again, output can be found at https://gist.github.com/blubber/acb88407f8f3afed7c34

Host Fails to Respond through Proxy

I have successfully run the script 'get_keyword_ideas.py' on my local machine without a proxy. When I deploy the script on a server with a proxy and I set the googleads.yaml https proxy I am unable to connect to the host.

I have verified that I am able to hit the following:

  • I am able to resolve googleapis.com, adwords.google.com with other applications
  • I have tried setting the proxy via os.environ['https_proxy'] = 'https://example:1234'

Error

TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

During handling of the above exception, another exception occurred: urllib.error.URLError: <urlopen error [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond>

Keyword Performance (AdWords) report downloads are empty

Hi,

Since yesterday I face some problems with downloading the keyword performance report (only shows the 2 header and footer lines). My code is below.
The strange thing is: other reports like AdPerformance work like expected, while using the same code. Also, downloading the Keyword report via .NET (we are migrating from .NET > Python) works just fine with the same API version.

When I exclude the Date column from my selection, the report will start downloading, but returns 500 MB gzipped (while it should be around 1 MB). I still put daterangetype to yesterday.

Anyone facing the same problems?

My code:

from googleads import adwords

def main(client):

report_downloader = client.GetReportDownloader(version='v201502')

report = {'reportName': 'KeyWordPerformance',
          'dateRangeType': 'YESTERDAY',
          'reportType': 'KEYWORDS_PERFORMANCE_REPORT',
          'downloadFormat': 'GZIPPED_CSV',
          'selector': {
              'fields': ["KeywordText", "AdGroupId", "CampaignId", "FirstPageCpc", "Id", "KeywordMatchType",
                         "QualityScore", "CriteriaDestinationUrl", "Date"]
          }
          }

report_file = open(<FileName>,  'wb')

report_downloader.DownloadReport(report, report_file)

report_file.close()

adwords_client = adwords.AdWordsClient.LoadFromStorage()
adwords_client.SetClientCustomerId()
main(adwords_client)

Issue on getting report and splitting right into utf8 bytes

When getting a report through DownloadReportAsString or DownloadReport, _DownloadReport is called. This method call _DownloadReportAsStream and read it chunk by chunk. The chunk size cannot be changed and it happens that, sometimes, the chunk end up right in the middle of and utf8 multibytes datablock.
I get an error while _DownloadReport tries to decode that chunk; it raises 'utf-8' codec can't decode byte 0xc3 in position 16383: unexpected end of data.

This problem breaks DownloadReportAsString which is annoying since "as string" could mean "as a single chunk".

I, myself, did a workaround where I use DownloadReportAsStream().read().decode().

Anyway I see several way of fixing that problem :

  • making the chunk size a parameters of the _DownloadReport method and make DownloadReportAsString pass -1 or 0 or whatever makes read() read the whole thing in one time
  • make the chunk size a class attribute
  • make the non-stream method use another download method than the stream one

I'd be glad to propose a patch for that.

dfp migration from v201311 to v201405

I'm seeing lot of changes between the v201311 to v201405.
There is no DfpUtils.py
FilterStatmeent has ToStatement and Increase offset etc. I dont see "IncreaseOffsetBy" object anymore.
In the UserService, UserRecord_Type column has changed to UserRecord.Type etc.
Overall "response" from the client has changed in format. for example, in v201311 it was response = user_service.getUsersByStatement(statement.ToStatement())[0]
but with v201405,
response = user_service.getUsersByStatement(statement.ToStatement()) is of a different format.

can you please point me to a page where all these changes are highlighted?

thanks!

User example “populate_first_party_audience_segments.py” doesn't work

I've tried the both v201403 and v201405, neither one of them is working.

Always gives me:
suds.WebFault: Server raised fault: 'Unmarshalling Error: cvc-type.2: The type definition cannot be abstract for element ns0:action. '

I am using a mac, and here is my python environments:
pip freeze
PyYAML==3.11
Pygments==1.6
gnureadline==6.3.3
googleads==1.0.6
httpie==0.8.0
ipdb==0.8
ipython==2.1.0
oauthlib==0.6.3
pytz==2014.4
requests==2.3.0
suds-jurko==0.6
wsgiref==0.1.2

DFP report errors cause read timeouts

When there is an API error returned from ReportService.getReportDownloadURL, DownloadReportToFile still attempts to download the report, resulting in a read timeout

Mapping Values Not Allowed

I am completely new to using this library, I've generated a refresh token and stored the the client id, refresh token, and secret all in the googleads.yaml file on the top level of the examples download. But everytime that I try to run get_campaigns.py I receive the following error. "yaml.scanner.ScannerError: mapping values are not allowed here
in "", line 5, column 57:"

I've already checked to make sure that I had spaces after all of the colons because I know that can cause problems, but I'm not sure what I am doing wrong. Any advice is greatly appreciated. It seems to me like maybe it doesn't like the / in the refresh token?

Examples not working and suds resolver errors

This is a reopening of #35 so refer to that issue for details

Running this on Ubuntu 12.04

@msaniscalchi I've set this up in a new virtualenv with only googleads + dependencies installed and the problem persists. You should be able to reproduce the error like this:

virtualenv gads;cd gads;source ./bin/activate
pip install googleads
wget https://github.com/googleads/googleads-python-lib/archive/master.zip
unzip master.zip
python googleads-python-lib-master/examples/adwords/v201409/optimization/estimate_keyword_traffic.py 

...

No handlers could be found for logger "suds.resolver"
Traceback (most recent call last):
  File "googleads-python-lib-master/examples/adwords/v201409/optimization/estimate_keyword_traffic.py", line 122, in <module>
main(adwords_client)
  File "googleads-python-lib-master/examples/adwords/v201409/optimization/estimate_keyword_traffic.py", line 101, in main
mean_avg_cpc = (long(estimate['min']['averageCpc']['microAmount']) +
  File "/home/vagrant/gads/local/lib/python2.7/site-packages/suds/sudsobject.py", line 154, in __getitem__
    return getattr(self, name)
AttributeError: 'StatsEstimate' object has no attribute 'averageCpc'

For good measure, here's the result when you add a logger for suds as well:
https://www.dropbox.com/s/oib6a6arg8ian1j/Screenshot%202014-11-14%2020.40.36.png?dl=0

Pushing an empty UrlList has no effect

We are currently migrating our product to the new destination URLs and are hitting a snag. Setting finalUrls and finalMobilUrls on regular keywords works fine, but after setting URLs it is impossible to clear the list. This is the dictionary that we are passing to the mutate method:

{'operand': {'adGroupId': '<redacted>',
          'criterion': {'id': '<redacted>',
                        'matchType': u'EXACT',
                        'text': u'some keyword',
                        'xsi_type': 'Keyword'},
          'destinationUrl': '',
          'finalMobileUrls': {'urls': []},
          'finalUrls': {'urls': []},
          'xsi_type': 'BiddableAdGroupCriterion'},

'operator': 'SET'}

The following XML blob is created by suds:

<?xml version="1.0" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="https://adwords.google.com/api/adwords/cm/v201502" xmlns:tns="https://adwords.google.com/api/adwords/cm/v201502" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SOAP-ENV:Header>
        <tns:RequestHeader>
            <tns:clientCustomerId>REDACTED</tns:clientCustomerId>
            <tns:developerToken>REDACTED</tns:developerToken>
            <tns:userAgent>(AwApi-Python, googleads/3.4.1, Python/2.7)</tns:userAgent>
            <tns:validateOnly>false</tns:validateOnly>
            <tns:partialFailure>false</tns:partialFailure>
        </tns:RequestHeader>
    </SOAP-ENV:Header>
    <ns0:Body>
        <ns1:mutate>
            <ns1:operations>
                <ns1:operator>SET</ns1:operator>
                <ns1:operand xsi:type="ns1:BiddableAdGroupCriterion">
                    <ns1:adGroupId>REDACTED</ns1:adGroupId>
                    <ns1:criterion xsi:type="ns1:Keyword">
                        <ns1:id>REDACTED</ns1:id>
                        <ns1:Criterion.Type>Keyword</ns1:Criterion.Type>
                        <ns1:text>some keyword</ns1:text>
                        <ns1:matchType>EXACT</ns1:matchType>
                    </ns1:criterion>
                    <ns1:AdGroupCriterion.Type>BiddableAdGroupCriterion</ns1:AdGroupCriterion.Type>
                    <ns1:destinationUrl/>
                </ns1:operand>
            </ns1:operations>
        </ns1:mutate>
    </ns0:Body>
</SOAP-ENV:Envelope>

In this XML blob the new (empty) UrlLists for finalUrls and finalMobileUrls are missing, and hence they are not cleared in AdWords. Setting the urls key to None or the finalUrls to {} or None doesn't solve the problem. It appears that either the adwords client or suds is removing the empty object.

Edit: this is using the latest versions of suds and googleads on Python 2.7.

201502 Traffic Estimator

Traffic Estimator doesn't seem to be working with latest adwords version!

(adwords)➜  adwords git:(master) ✗ python keyword_estimate.py
Traceback (most recent call last):
  File "keyword_estimate.py", line 28, in <module>
    traffic_estimator_service = adwords_client.GetService('TrafficEstimatorService', version='v201502')
  File "/Users//.virtualenvs/adwords/lib/python2.7/site-packages/googleads/adwords.py", line 262, in GetService
    'Supported versions: %s' % (version, _SERVICE_MAP.keys()))
googleads.errors.GoogleAdsValueError: Unrecognized version of the AdWords API. Version given: v201502 Supported versions: ['v201409', 'v201406']

create_dfa_client_without_yaml.py example doesn't work

First of all:

dfa_client.GetService('CampaignService')

isn't right, because there is no 'CampaignService':

googleads.errors.GoogleAdsValueError: Unrecognized service for the DFA API. Service given: CampaignService Supported services: ('ad', 'advertiser', 'advertisergroup', 'campaign', 'changelog', 'contentcategory', 'c
reative', 'creativefield', 'creativegroup', 'login', 'network', 'placement', 'site', 'size', 'spotlight', 'strategy', 'subnetwork', 'user', 'userrole', 'report')

Calling:

  results = dfa_client.GetService('campaign').getCampaignsByCriteria({})

Results in:

ERROR:suds.client:<suds.sax.document.Document instance at 0x00000000032899C8>
Traceback (most recent call last):
  File "create_dfa_client_without_yaml.py", line 60, in <module>
    APPLICATION_NAME)
  File "create_dfa_client_without_yaml.py", line 51, in main
    results = dfa_client.GetService('campaign').getCampaignsByCriteria({})
  File "C:\Python27\lib\site-packages\googleads\common.py", line 229, in MakeSoapRequest
    for arg in args])
  File "C:\Python27\lib\site-packages\suds\client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "C:\Python27\lib\site-packages\suds\client.py", line 581, in invoke
    result = self.send(soapenv)
  File "C:\Python27\lib\site-packages\suds\client.py", line 619, in send
    description=tostr(e), original_soapenv=original_soapenv)
  File "C:\Python27\lib\site-packages\suds\client.py", line 670, in process_reply
    raise WebFault(fault, replyroot)
suds.WebFault: Server raised fault: '20001 - You must specify request parameter for method .'

It seems like this library doesn't work at all - whatever call I make I get:

suds.WebFault: Server raised fault: '20001 - You must specify request parameter for method .'

I tried it with Python 2.7.

Version v201409 no fully supported

File "/usr/local/lib/python2.7/dist-packages/googleads/adwords.py", line 261, in GetService
'Supported versions: %s' % (version, _SERVICE_MAP.keys()))
GoogleAdsValueError: Unrecognized version of the AdWords API. Version given: v201409 Supported versions: ['v201402', 'v201406']

But GetReportDownloader works fine:

report_downloader = con.adwords_client.GetReportDownloader(version=version)
report_downloader.DownloadReport(report_definition, output=output)

advertisingChannelSubType messed up the web-interface

full details + screenshot:
https://groups.google.com/forum/#!topic/adwords-api/x9r3BxO1JHA

in short:
trying to 'ADD' new campaign with specific subtype messes-up adwords web-interface..

symptoms:
It's not possible to edit the campaign type
It's not possible to edit the campaign sub type
type & subtype display differs between a manually entered subtype, and an API-generated campaign.

consequently, also, i can't verify manually that the API setting is correct.

This is the operation:

                'operator': 'ADD',
                'operand': {
                    'name': 'eshkolit', 
                    'status': 'ENABLED',
                    'advertisingChannelType': 'DISPLAY',     
                    'advertisingChannelSubType': 'DISPLAY_MOBILE_APP',
                    (... more settings...)
               }

The operation runs without an error.

BTW
when I select the API -generated campaign via API, I get the same subtype given.
when I select the manually-created-campaign via API, I do NOT see the subtype.

SSL Errors

Posted in adwords API forum. Asked to open an issue here instead.

Hi,

We are using the python adspygoogle package and we are seeing two kinds of SSL errors. Though both these are intermittent, they are not infrequent.

Traceback:
File "/home/googlelibs/adwords_ops.py", line 2153, in modify_ad
response = client.GetAdGroupAdService('https://adwords.google.com').Mutate(ad_operations)
File "/home/googlelibs/lib64/python2.6/site-packages/adspygoogle/common/GenericApiService.py", line 365, in CallMethod
self._HandleLogsAndErrors(buf, start_time, stop_time, error)
File "/home/googlelibs/lib64/python2.6/site-packages/adspygoogle/adwords/GenericAdWordsService.py", line 256, in _HandleLogsAndErrors
raise Error(e)
Error: {'data': SSLError('The read operation timed out',)}

In this case is there anyway the timeout can be increased in the API calls without making changes to the actual adspygoogle code?

In another scenario, we get a lot of SSL errors of the kinds:
SSLError: [Errno 1] _ssl.c:1331: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac
SSLError: [Errno 1] _ssl.c:490: error:0D078094:asn1 encoding routines:ASN1_ITEM_EX_D2I:sequence length mismatch
Error: {'data': SSLError(1, '_ssl.c:490: error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01')}
Error: {'data': SSLError(1, '_ssl.c:490: error:1408C095:SSL routines:SSL3_GET_FINISHED:digest check failed')}
Error: {'data': SSLError(1, '_ssl.c:490: error:04091068:rsa routines:INT_RSA_VERIFY:bad signature')}
SSLError: [Errno 1] _ssl.c:1331: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac

We are using RHEL 6.4. Please let us know if someone has any idea on these. I would like to emphasize that these are intermittent issues but not infrequent.

Thanks for all the help in advance.

Problem with examples or missed documentation of important steps to setup connection

I was passed refresh token generation and trying connect but it not works since some problems with certificate in Python 2.7.10 - can you explain why it is not working?

https://github.com/googleads/googleads-python-lib/blob/master/examples/adwords/authentication/create_adwords_client_without_yaml.py

Using example code generates exception - some steps is not described in documentation:

C:\root\Python27\python.exe "C:/Users/Crezary Wagner/PycharmProjects/learn-adwords/src/examples/create_adwords_client_without_yaml.py"
Traceback (most recent call last):
File "C:/Users/Crezary Wagner/PycharmProjects/learn-adwords/src/examples/create_adwords_client_without_yaml.py", line 56, in
CLIENT_CUSTOMER_ID)
File "C:/Users/Crezary Wagner/PycharmProjects/learn-adwords/src/examples/create_adwords_client_without_yaml.py", line 50, in main
customer = adwords_client.GetService('CustomerService').get()
File "C:\root\Python27\lib\site-packages\googleads\adwords.py", line 256, in GetService
proxy=proxy_option, cache=self.cache, timeout=3600)
File "C:\root\Python27\lib\site-packages\suds\client.py", line 115, in init
self.wsdl = reader.open(url)
File "C:\root\Python27\lib\site-packages\suds\reader.py", line 150, in open
d = self.fn(url, self.options)
File "C:\root\Python27\lib\site-packages\suds\wsdl.py", line 136, in init
d = reader.open(url)
File "C:\root\Python27\lib\site-packages\suds\reader.py", line 74, in open
d = self.download(url)
File "C:\root\Python27\lib\site-packages\suds\reader.py", line 92, in download
fp = self.options.transport.open(Request(url))
File "C:\root\Python27\lib\site-packages\suds\transport\https.py", line 62, in open
return HttpTransport.open(self, request)
File "C:\root\Python27\lib\site-packages\suds\transport\http.py", line 67, in open
return self.u2open(u2request)
File "C:\root\Python27\lib\site-packages\suds\transport\http.py", line 132, in u2open
return url.open(u2request, timeout=tm)
File "C:\root\Python27\lib\urllib2.py", line 431, in open
response = self._open(req, data)
File "C:\root\Python27\lib\urllib2.py", line 449, in _open
'_open', req)
File "C:\root\Python27\lib\urllib2.py", line 409, in _call_chain
result = func(*args)
File "C:\root\Python27\lib\urllib2.py", line 1240, in https_open
context=self._context)
File "C:\root\Python27\lib\urllib2.py", line 1197, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>

Get all line items example gives an error

I've copied and pasted the code from the following:

https://github.com/googleads/googleads-python-lib/blob/master/examples/dfp/v201502/line_item_service/get_all_line_items.py

When I run it I get an error:

  File "/google-drive/googledrive/googledrive/dfp/dfp.py", line 36, in main
    statement.ToStatement())
  File "/google-drive/googledrive/venv/local/lib/python2.7/site-packages/googleads/common.py", line 296, in MakeSoapRequest
    for arg in args])
  File "/google-drive/googledrive/venv/local/lib/python2.7/site-packages/suds/client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "/google-drive/googledrive/venv/local/lib/python2.7/site-packages/suds/client.py", line 581, in invoke
    result = self.send(soapenv)
  File "/google-drive/googledrive/venv/local/lib/python2.7/site-packages/suds/client.py", line 619, in send
    description=tostr(e), original_soapenv=original_soapenv)
  File "/google-drive/googledrive/venv/local/lib/python2.7/site-packages/suds/client.py", line 670, in process_reply
    raise WebFault(fault, replyroot)
suds.WebFault: Server raised fault: '[AuthenticationError.NETWORK_CODE_REQUIRED @ ]'

The only change I've made to the example code is how I create the client. I'm using Storage from oauth2client and am creating a DFP client with:

credentials = get_credentials()            # returns a OAuth2Credentials object

    oauth2_client = oauth2.GoogleRefreshTokenClient(
        client_id=credentials.client_id,
        client_secret=credentials.client_secret,
        refresh_token=credentials.refresh_token)

    # then as per the example:
    dfp_client = dfp.DfpClient(oauth2_client, 'my-app')

    line_item_service = dfp_client.GetService('LineItemService', version='v201502')

ValueError: check_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED

I just upgraded from v201409 to v201502 by running pip install --upgrade googleads and without doing any other changes, I suddenly can no longer use any of the googleads services. Any call, for example, to get a list of all campaigns, now results in a ValueError exception inside the http lib, where it claims it needs an SSL context with either CERT_OPTIONAL or CERT_REQUIRED?

DEBUG:suds.transport.http:opening (https://adwords.google.com/api/adwords/cm/v201502/CampaignService?wsdl)
INFO:oauth2client.client:Refreshing access_token
Traceback (most recent call last):
   ...
    page = campaign_service.get(selector)
  File "C:\Python34\lib\site-packages\googleads\common.py", line 294, in MakeSoapRequest
    self._header_handler.SetHeaders(self.suds_client)
  File "C:\Python34\lib\site-packages\googleads\adwords.py", line 378, in SetHeaders
    headers=self._adwords_client.oauth2_client.CreateHttpHeader())
  File "C:\Python34\lib\site-packages\googleads\oauth2.py", line 150, in CreateHttpHeader
    self.Refresh()
  File "C:\Python34\lib\site-packages\googleads\oauth2.py", line 166, in Refresh
    self.disable_ssl_certificate_validation)))
  File "C:\Python34\lib\site-packages\oauth2client\client.py", line 577, in refresh
    self._refresh(http.request)
  File "C:\Python34\lib\site-packages\oauth2client\client.py", line 748, in _refresh
    self._do_refresh_request(http_request)
  File "C:\Python34\lib\site-packages\oauth2client\client.py", line 777, in _do_refresh_request
    self.token_uri, method='POST', body=body, headers=headers)
  File "C:\Python34\lib\site-packages\httplib2\__init__.py", line 1174, in request
    self.disable_ssl_certificate_validation)
  File "C:\Python34\lib\site-packages\httplib2\__init__.py", line 829, in __init__
    check_hostname=True)
  File "C:\Python34\lib\http\client.py", line 1211, in __init__
    raise ValueError("check_hostname needs a SSL context with "
ValueError: check_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED

I'm running Python 3.4 on Windows with not much installed in terms of other packages. The output from pip list is:

feedparser (5.1.3)
googleads (3.2.0)
httplib2 (0.9)
oauth2client (1.4.7)
oauthlib (0.7.2)
pip (6.1.1)
pyasn1 (0.1.7)
pyasn1-modules (0.0.5)
pyodbc (3.0.7)
PySocks (1.5.3)
pytz (2015.2)
PyYAML (3.11)
rsa (3.1.4)
setuptools (15.0)
six (1.9.0)
suds-jurko (0.6)

Problem with ReportDownloader behind proxy

Hi guys,

I was working on a fork I did from version 1.0.4 and it worked fine behind our proxy.
I tried to update to version 2.1.0 now and it seems it doesn't work yet. On my fork I commented the following lines to make it work:

    #TODO: Removed by Rodrigo (doesn't work)
    #if self._adwords_client.https_proxy:
    #  request.set_proxy(self._adwords_client.https_proxy, 'https')
    try:
      return urllib2.urlopen(request)
    except urllib2.HTTPError, e:
      raise self._ExtractError(e)

At this point I don't think is necessary to set the proxy.
If I keep it uncommented I got this error:

Traceback (most recent call last):
  File "test_new.py", line 51, in <module>
    main(adwords_client)
  File "test_new.py", line 31, in main
    report_downloader.DownloadReport(report, sys.stdout)
  File "/opt/python2.7/lib/python2.7/site-packages/googleads-2.1.0-py2.7.egg/googleads/adwords.py", line 510, in DownloadReport
    skip_report_summary)
  File "/opt/python2.7/lib/python2.7/site-packages/googleads-2.1.0-py2.7.egg/googleads/adwords.py", line 745, in _DownloadReport
    skip_report_summary)
  File "/opt/python2.7/lib/python2.7/site-packages/googleads-2.1.0-py2.7.egg/googleads/adwords.py", line 790, in _DownloadReportAsStream
    return urllib2.urlopen(request)
  File "/opt/python2.7/lib/python2.7/urllib2.py", line 127, in urlopen
    return _opener.open(url, data, timeout)
  File "/opt/python2.7/lib/python2.7/urllib2.py", line 404, in open
    response = self._open(req, data)
  File "/opt/python2.7/lib/python2.7/urllib2.py", line 422, in _open
    '_open', req)
  File "/opt/python2.7/lib/python2.7/urllib2.py", line 382, in _call_chain
    result = func(*args)
  File "/opt/python2.7/lib/python2.7/urllib2.py", line 1222, in https_open
    return self.do_open(httplib.HTTPSConnection, req)
  File "/opt/python2.7/lib/python2.7/urllib2.py", line 1184, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error Tunnel connection failed: 404 Not Found>

Please check #5 to see the previous issue I raised.

Document an example of using oauth2 assertion flow with AdWords API

According to the guide to using oauth service accounts with AdWords, it would appear that service accounts need to use the "Assertion Flow" to impersonate users.

The examples shown indicate that the Java client library has built-in methods for enabling this use case. Can this be done from the python client? If so, having an example or helper method would be appreciated.

Would subclassing googleads.oauth2.GoogleOAuth2Client be the place to implement this behavior? What does the authorization header need to contain to allow impersonation/assertion?

estimate_keyword_traffic.py example throws AttributeError

When running the example, an AttributeError is thrown: https://gist.github.com/schmilblick/0ab036790c7404055685

When debugging it I found additional errors. I went step by step through the example, and when reaching the line:

estimates = traffic_estimator_service.get(selector)

Suds logs the following errors:

[2014-10-21 12:..] [/.../suds/resolver.py:134] [ERROR] (Money) not-found
[2014-10-21 12:..] [/.../suds/resolver.py:116] [ERROR] path: Money, not-found
[2014-10-21 12:..] [/.../suds/resolver.py:134] [ERROR] (Keyword) not-found
[2014-10-21 12:..] [/.../suds/resolver.py:116] [ERROR] path: Keyword, not-found
[2014-10-21 12:..] [/.../suds/resolver.py:134] [ERROR] (Location) not-found
[2014-10-21 12:..] [/.../suds/resolver.py:116] [ERROR] path: Location, not-found
[2014-10-21 12:..] [/.../suds/resolver.py:134] [ERROR] (Language) not-found
[2014-10-21 12:..] [/.../suds/resolver.py:116] [ERROR] path: Language, not-found

I am using the example code from: https://github.com/googleads/googleads-python-lib/blob/master/examples/adwords/v201409/optimization/estimate_keyword_traffic.py

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.