Skip to content

Commit ae4093a

Browse files
authored
Create Python 3.8 compatible copy of library version 28.0.0. (#1025)
1 parent d059569 commit ae4093a

File tree

5 files changed

+36
-45
lines changed

5 files changed

+36
-45
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
* 28.0.0.post1
2+
- Temporarily remove incompatibility with Python 3.8.
3+
14
* 28.0.0
25
- Google Ads API v21_0 release.
36
- Updated to Google Ads API v19_0 and v20_0 to include EU political advertising changes.

google/ads/googleads/__init__.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@
1919
import google.ads.googleads.errors
2020
import google.ads.googleads.util
2121

22-
VERSION = "28.0.0"
22+
VERSION = "28.0.0.post1"
2323

24-
# Checks if the current runtime is Python 3.9.
25-
if sys.version_info.major == 3 and sys.version_info.minor <= 9:
26-
warnings.warn(
27-
"Support for Python versions less than 3.9 is deprecated in the "
28-
"google-ads package. Please upgrade to Python 3.10 or higher.",
29-
category=DeprecationWarning,
30-
)
24+
# Warns that this version of the library is intended as a temporary workaround
25+
# for Python 3.8 users.
26+
warnings.warn(
27+
"This version of google-ads-python (28.0.0.post1) is only intended for "
28+
"use by Python 3.8 users who cannot upgrade to a newer version of Python "
29+
"and are blocked from accessing the Google Ads API due to changes made to"
30+
"comply with European Union Political Ads Regulation. For more details, "
31+
"see: https://ads-developers.googleblog.com/2025/08/eu-par-google-ads-api-scripts.html. "
32+
"We recommend upgrading to Python >=3.10 and google-ads-python >=28.0.0 "
33+
"as soon as possible.",
34+
category=Warning,
35+
)

noxfile.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import pathlib
1818

1919

20-
PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]
20+
PYTHON_VERSIONS = ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
2121
PROTOBUF_IMPLEMENTATIONS = ["python", "upb"]
2222

2323
TEST_COMMAND = [
@@ -39,20 +39,13 @@
3939
"--omit=.nox/*,examples/*,*/__init__.py",
4040
]
4141
FREEZE_COMMAND = ["python", "-m", "pip", "freeze"]
42-
TEST_DEPENDENCIES = [
43-
"pyfakefs>=5.0.0,<6.0",
44-
"coverage==6.5.0",
45-
]
4642
CURRENT_DIR = pathlib.Path(__file__).parent.absolute()
4743
CONSTRAINTS_DIR = os.path.join(CURRENT_DIR, "tests", "constraints")
4844

49-
5045
@nox.session(python=PYTHON_VERSIONS)
5146
@nox.parametrize("protobuf_implementation", PROTOBUF_IMPLEMENTATIONS)
5247
def tests(session, protobuf_implementation):
53-
session.install("-e", ".")
54-
# modules for testing
55-
session.install(*TEST_DEPENDENCIES)
48+
session.install("-e", ".[tests]")
5649
session.run(*FREEZE_COMMAND)
5750
session.run(
5851
*TEST_COMMAND,
@@ -79,8 +72,8 @@ def tests_minimum_dependency_versions(session, protobuf_implementation):
7972

8073
constraints_file = os.path.join(CONSTRAINTS_DIR, "minimums", filename)
8174

82-
session.install("-e", ".")
83-
session.install(*TEST_DEPENDENCIES, "-c", constraints_file)
75+
session.install("-e", ".[tests]", "-c", constraints_file)
76+
# session.install()
8477
session.run(*FREEZE_COMMAND)
8578
session.run(
8679
*TEST_COMMAND,

pyproject.toml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,21 @@ build-backend = "setuptools.build_meta"
1818

1919
[project]
2020
name = "google-ads"
21-
version = "28.0.0"
21+
version = "28.0.0.post1"
2222
description = "Client library for the Google Ads API"
2323
readme = "./README.rst"
24-
requires-python = ">=3.9, <3.14"
25-
license = "Apache-2.0"
24+
requires-python = ">=3.8, <3.14"
25+
license = { file = "LICENSE" }
26+
2627
authors = [
2728
{name = "Google LLC", email = "[email protected]"}
2829
]
30+
2931
classifiers = [
30-
"Intended Audience :: Developers",
31-
"Development Status :: 5 - Production/Stable",
3232
"Intended Audience :: Developers",
3333
"Programming Language :: Python",
3434
"Programming Language :: Python :: 3",
35+
"Programming Language :: Python :: 3.8",
3536
"Programming Language :: Python :: 3.9",
3637
"Programming Language :: Python :: 3.10",
3738
"Programming Language :: Python :: 3.11",
@@ -59,7 +60,11 @@ dependencies = [
5960
]
6061

6162
[project.optional-dependencies]
62-
tests = ["nox >= 2020.12.31, < 2022.6"]
63+
tests = [
64+
"nox >= 2020.12.31, < 2022.6",
65+
"pyfakefs>=5.0.0,<6.0",
66+
"coverage==6.5.0",
67+
]
6368

6469
[project.urls]
6570
Repository = "https://github.com/googleads/google-ads-python"

tests/interceptors/logging_interceptor_test.py

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,7 @@ def test_intercept_unary_unary_successful_request(self):
305305
)
306306
mock_trailing_metadata = mock_response.trailing_metadata()
307307

308-
with (
309-
mock.patch("logging.config.dictConfig"),
310-
mock.patch("google.ads.googleads.client._logger") as mock_logger,
311-
):
308+
with mock.patch("logging.config.dictConfig"), mock.patch("google.ads.googleads.client._logger") as mock_logger:
312309
interceptor = self._create_test_interceptor(logger=mock_logger)
313310
interceptor.intercept_unary_unary(
314311
mock_continuation_fn, mock_client_call_details, mock_request
@@ -361,10 +358,7 @@ def mock_add_done_callback(fn):
361358

362359
mock_continuation_fn = mock.Mock(return_value=mock_response)
363360

364-
with (
365-
mock.patch("logging.config.dictConfig"),
366-
mock.patch("google.ads.googleads.client._logger") as mock_logger,
367-
):
361+
with mock.patch("logging.config.dictConfig"), mock.patch("google.ads.googleads.client._logger") as mock_logger:
368362
interceptor = self._create_test_interceptor(logger=mock_logger)
369363
interceptor.intercept_unary_stream(
370364
mock_continuation_fn, mock_client_call_details, mock_request
@@ -416,10 +410,7 @@ def test_intercept_unary_unary_failed_request(self):
416410
mock_continuation_fn = self._get_mock_continuation_fn(fail=True)
417411
mock_request = self._get_mock_request()
418412

419-
with (
420-
mock.patch("logging.config.dictConfig"),
421-
mock.patch("google.ads.googleads.client._logger") as mock_logger,
422-
):
413+
with mock.patch("logging.config.dictConfig"), mock.patch("google.ads.googleads.client._logger") as mock_logger:
423414
interceptor = self._create_test_interceptor(logger=mock_logger)
424415
mock_response = interceptor.intercept_unary_unary(
425416
mock_continuation_fn, mock_client_call_details, mock_request
@@ -472,10 +463,7 @@ def mock_add_done_callback(fn):
472463
mock_response.add_done_callback = mock_add_done_callback
473464
mock_continuation_fn = mock.Mock(return_value=mock_response)
474465

475-
with (
476-
mock.patch("logging.config.dictConfig"),
477-
mock.patch("google.ads.googleads.client._logger") as mock_logger,
478-
):
466+
with mock.patch("logging.config.dictConfig"), mock.patch("google.ads.googleads.client._logger") as mock_logger:
479467
interceptor = self._create_test_interceptor(logger=mock_logger)
480468
mock_response = interceptor.intercept_unary_stream(
481469
mock_continuation_fn, mock_client_call_details, mock_request
@@ -554,10 +542,7 @@ def test_parse_exception_to_str_transport_failure(self):
554542
"""Calls _format_json_object with error obj's debug_error_string."""
555543
interceptor = self._create_test_interceptor()
556544

557-
with (
558-
mock.patch("logging.config.dictConfig"),
559-
mock.patch.object(interceptor, "format_json_object") as mock_parser,
560-
):
545+
with mock.patch("logging.config.dictConfig"), mock.patch.object(interceptor, "format_json_object") as mock_parser:
561546
mock_exception = self._get_mock_transport_exception()
562547
interceptor._parse_exception_to_str(mock_exception)
563548
mock_parser.assert_called_once_with(

0 commit comments

Comments
 (0)