Skip to content

Commit c942042

Browse files
authored
Add utility to format composite resource names (#52)
1 parent 663685b commit c942042

File tree

7 files changed

+85
-21
lines changed

7 files changed

+85
-21
lines changed

examples/basic_operations/pause_ad.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919
import six
2020
import sys
2121

22-
import google.ads.google_ads.client
2322
from google.api_core import protobuf_helpers
23+
from google.ads.google_ads.client import GoogleAdsClient
24+
from google.ads.google_ads.util import ResourceName
2425

2526

2627
def main(client, customer_id, ad_group_id, ad_id):
@@ -30,7 +31,7 @@ def main(client, customer_id, ad_group_id, ad_id):
3031

3132
ad_group_ad = ad_group_ad_operation.update
3233
ad_group_ad.resource_name = ad_group_ad_service.ad_group_ad_path(
33-
customer_id, '%s_%s' % (ad_group_id, ad_id))
34+
customer_id, ResourceName.format_composite(ad_group_id, ad_id))
3435
ad_group_ad.status = client.get_type('AdGroupStatusEnum',
3536
version='v1').PAUSED
3637
fm = protobuf_helpers.field_mask(None, ad_group_ad)
@@ -56,9 +57,7 @@ def main(client, customer_id, ad_group_id, ad_id):
5657
if __name__ == '__main__':
5758
# GoogleAdsClient will read the google-ads.yaml configuration file in the
5859
# home directory if none is specified.
59-
google_ads_client = (google.ads.google_ads.client.GoogleAdsClient
60-
.load_from_storage())
61-
60+
google_ads_client = GoogleAdsClient.load_from_storage()
6261
parser = argparse.ArgumentParser(
6362
description=('Pauses an ad in the specified customer\'s ad group.'))
6463
# The following argument(s) should be provided to run the example.

examples/basic_operations/remove_ad.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
import six
2020
import sys
2121

22-
import google.ads.google_ads.client
23-
22+
from google.ads.google_ads.client import GoogleAdsClient
23+
from google.ads.google_ads.util import ResourceName
2424

2525
def main(client, customer_id, ad_group_id, ad_id):
2626
ad_group_ad_service = client.get_service('AdGroupAdService', version='v1')
2727
ad_group_ad_operation = client.get_type('AdGroupAdOperation', version='v1')
2828

2929
resource_name = ad_group_ad_service.ad_group_ad_path(
30-
customer_id, '%s_%s' % (ad_group_id, ad_id))
30+
customer_id, ResourceName.format_composite(ad_group_id, ad_id))
3131
ad_group_ad_operation.remove = resource_name
3232

3333
try:
@@ -50,9 +50,7 @@ def main(client, customer_id, ad_group_id, ad_id):
5050
if __name__ == '__main__':
5151
# GoogleAdsClient will read the google-ads.yaml configuration file in the
5252
# home directory if none is specified.
53-
google_ads_client = (google.ads.google_ads.client.GoogleAdsClient
54-
.load_from_storage())
55-
53+
google_ads_client = GoogleAdsClient.load_from_storage()
5654
parser = argparse.ArgumentParser(
5755
description=('Removes an ad from the specified customer\'s ad group.'))
5856
# The following argument(s) should be provided to run the example.

examples/basic_operations/remove_keyword.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@
1919
import six
2020
import sys
2121

22-
import google.ads.google_ads.client
22+
from google.ads.google_ads.client import GoogleAdsClient
23+
from google.ads.google_ads.util import ResourceName
2324

2425

2526
def main(client, customer_id, ad_group_id, criteria_id):
2627
agc_service = client.get_service('AdGroupCriterionService', version='v1')
2728
agc_operation = client.get_type('AdGroupCriterionOperation', version='v1')
2829

2930
resource_name = agc_service.ad_group_criteria_path(
30-
customer_id, '%s_%s' % (ad_group_id, criteria_id))
31+
customer_id, ResourceName.format_composite(ad_group_id, criteria_id))
3132
agc_operation.remove = resource_name
3233

3334
try:
@@ -49,9 +50,7 @@ def main(client, customer_id, ad_group_id, criteria_id):
4950
if __name__ == '__main__':
5051
# GoogleAdsClient will read the google-ads.yaml configuration file in the
5152
# home directory if none is specified.
52-
google_ads_client = (google.ads.google_ads.client.GoogleAdsClient
53-
.load_from_storage())
54-
53+
google_ads_client = GoogleAdsClient.load_from_storage()
5554
parser = argparse.ArgumentParser(
5655
description=('Removes given campaign for the specified customer.'))
5756
# The following argument(s) should be provided to run the example.

examples/basic_operations/update_keyword.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919
import six
2020
import sys
2121

22-
import google.ads.google_ads.client
2322
from google.api_core import protobuf_helpers
23+
from google.ads.google_ads.client import GoogleAdsClient
24+
from google.ads.google_ads.util import ResourceName
2425

2526

2627
def main(client, customer_id, ad_group_id, criterion_id):
@@ -31,7 +32,7 @@ def main(client, customer_id, ad_group_id, criterion_id):
3132

3233
ad_group_criterion = ad_group_criterion_operation.update
3334
ad_group_criterion.resource_name = agc_service.ad_group_criteria_path(
34-
customer_id, '%s_%s' % (ad_group_id, criterion_id))
35+
customer_id, ResourceName.format_composite(ad_group_id, criterion_id))
3536
ad_group_criterion.status = (client.get_type('AdGroupCriterionStatusEnum',
3637
version='v1')
3738
.ENABLED)
@@ -59,9 +60,7 @@ def main(client, customer_id, ad_group_id, criterion_id):
5960
if __name__ == '__main__':
6061
# GoogleAdsClient will read the google-ads.yaml configuration file in the
6162
# home directory if none is specified.
62-
google_ads_client = (google.ads.google_ads.client.GoogleAdsClient
63-
.load_from_storage())
64-
63+
google_ads_client = GoogleAdsClient.load_from_storage()
6564
parser = argparse.ArgumentParser(
6665
description=('Pauses an ad in the specified customer\'s ad group.'))
6766
# The following argument(s) should be provided to run the example.

google/ads/google_ads/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import google.ads.google_ads.client
2020
import google.ads.google_ads.errors
21+
import google.ads.google_ads.util
2122

2223

2324
VERSION = '1.2.0'

google/ads/google_ads/util.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2019 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Common utilities for the Google Ads API client library."""
15+
16+
17+
class ResourceName:
18+
19+
# As of Google Ads API v1 composite resource names are
20+
# delimited by a "~" character.
21+
_COMPOSITE_DELIMITER = '~'
22+
23+
@classmethod
24+
def format_composite(cls, *arg):
25+
"""Formats any number of ID strings into a single composite string.
26+
27+
Note: this utility does not construct an entire resource name string.
28+
It only formats the composite portion for IDs that are not globally
29+
unique, for example an ad_group_ad.
30+
31+
Args:
32+
arg: Any number of str IDs for resources such as ad_groups or
33+
ad_group_ads.
34+
35+
Returns:
36+
A str of all the given strs concatenated with the compsite
37+
delimiter.
38+
39+
Raises:
40+
TypeError: If anything other than a string is passed in.
41+
"""
42+
return cls._COMPOSITE_DELIMITER.join(arg)
43+

tests/util_test.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2019 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Tests for the Google Ads API client library utilities."""
15+
16+
17+
from unittest import TestCase
18+
19+
from google.ads.google_ads.util import ResourceName
20+
21+
class ResourceNameTest(TestCase):
22+
def test_format_composite(self):
23+
composite = ResourceName.format_composite('test', 'test')
24+
self.assertEqual(composite, 'test~test')
25+

0 commit comments

Comments
 (0)