Skip to content

Commit 8c19609

Browse files
authored
fix: restore support for grpcio-gcp (#418)
docs: add a note that grpcio-gcp is only supported in environments with protobuf < 4.x.x docs: raise DeprecationWarning when 'grpcio-gcp' is used fix(deps): require protobuf >= 3.20.1
1 parent 29aa9ef commit 8c19609

File tree

8 files changed

+129
-17
lines changed

8 files changed

+129
-17
lines changed

.github/sync-repo-settings.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ branchProtectionRules:
1111
# No Kokoro: the following are Github actions
1212
- 'lint'
1313
- 'mypy'
14+
- 'unit_grpc_gcp-3.7'
15+
- 'unit_grpc_gcp-3.8'
16+
- 'unit_grpc_gcp-3.9'
17+
- 'unit_grpc_gcp-3.10'
1418
- 'unit-3.7'
1519
- 'unit-3.8'
1620
- 'unit-3.9'

.github/workflows/unittest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
runs-on: ubuntu-latest
1212
strategy:
1313
matrix:
14-
option: ["", "_wo_grpc"]
14+
option: ["", "_grpc_gcp", "_wo_grpc"]
1515
python:
1616
- "3.7"
1717
- "3.8"

google/api_core/grpc_helpers.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import collections
1818
import functools
19+
import warnings
1920

2021
import grpc
2122

@@ -24,6 +25,27 @@
2425
import google.auth.credentials
2526
import google.auth.transport.grpc
2627
import google.auth.transport.requests
28+
import google.protobuf
29+
30+
PROTOBUF_VERSION = google.protobuf.__version__
31+
32+
# The grpcio-gcp package only has support for protobuf < 4
33+
if PROTOBUF_VERSION[0:2] == "3.":
34+
try:
35+
import grpc_gcp
36+
37+
warnings.warn(
38+
"""Support for grpcio-gcp is deprecated. This feature will be
39+
removed from `google-api-core` after January 1, 2024. If you need to
40+
continue to use this feature, please pin to a specific version of
41+
`google-api-core`.""",
42+
DeprecationWarning,
43+
)
44+
HAS_GRPC_GCP = True
45+
except ImportError:
46+
HAS_GRPC_GCP = False
47+
else:
48+
HAS_GRPC_GCP = False
2749

2850

2951
# The list of gRPC Callable interfaces that return iterators.
@@ -275,7 +297,9 @@ def create_channel(
275297
default_scopes (Sequence[str]): Default scopes passed by a Google client
276298
library. Use 'scopes' for user-defined scopes.
277299
default_host (str): The default endpoint. e.g., "pubsub.googleapis.com".
278-
kwargs: Additional key-word args passed to :func:`grpc.secure_channel`.
300+
kwargs: Additional key-word args passed to
301+
:func:`grpc_gcp.secure_channel` or :func:`grpc.secure_channel`.
302+
Note: `grpc_gcp` is only supported in environments with protobuf < 4.0.0.
279303
280304
Returns:
281305
grpc.Channel: The created channel.
@@ -294,6 +318,8 @@ def create_channel(
294318
default_host=default_host,
295319
)
296320

321+
if HAS_GRPC_GCP:
322+
return grpc_gcp.secure_channel(target, composite_credentials, **kwargs)
297323
return grpc.secure_channel(target, composite_credentials, **kwargs)
298324

299325

noxfile.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
# 'docfx' is excluded since it only needs to run in 'docs-presubmit'
3333
nox.options.sessions = [
3434
"unit",
35+
"unit_grpc_gcp",
3536
"unit_wo_grpc",
3637
"cover",
3738
"pytype",
@@ -142,6 +143,20 @@ def unit(session):
142143
default(session)
143144

144145

146+
@nox.session(python=["3.6", "3.7", "3.8", "3.9", "3.10"])
147+
def unit_grpc_gcp(session):
148+
"""Run the unit test suite with grpcio-gcp installed."""
149+
constraints_path = str(
150+
CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt"
151+
)
152+
# Install grpcio-gcp
153+
session.install("-e", ".[grpcgcp]", "-c", constraints_path)
154+
# Install protobuf < 4.0.0
155+
session.install("protobuf<4.0.0")
156+
157+
default(session)
158+
159+
145160
@nox.session(python=["3.8", "3.10"])
146161
def unit_wo_grpc(session):
147162
"""Run the unit test suite w/o grpcio installed"""

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
release_status = "Development Status :: 5 - Production/Stable"
3131
dependencies = [
3232
"googleapis-common-protos >= 1.56.2, < 2.0dev",
33-
"protobuf >= 3.15.0, <5.0.0dev",
33+
"protobuf >= 3.20.1, <5.0.0dev",
3434
"google-auth >= 1.25.0, < 3.0dev",
3535
"requests >= 2.18.0, < 3.0.0dev",
3636
]
3737
extras = {
3838
"grpc": ["grpcio >= 1.33.2, < 2.0dev", "grpcio-status >= 1.33.2, < 2.0dev"],
39+
"grpcgcp": "grpcio-gcp >= 0.2.2, < 1.0dev",
40+
"grpcio-gcp": "grpcio-gcp >= 0.2.2, < 1.0dev",
3941
}
4042

4143

testing/constraints-3.7.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
# e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev",
77
# Then this file should have foo==1.14.0
88
googleapis-common-protos==1.56.2
9-
protobuf==3.15.0
9+
protobuf==3.20.1
1010
google-auth==1.25.0
1111
requests==2.18.0
1212
packaging==14.3
1313
grpcio==1.33.2
1414
grpcio-status==1.33.2
15+
grpcio-gcp==0.2.2

testing/constraints-3.8.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
googleapis-common-protos==1.56.3
2+
protobuf==4.21.5

tests/unit/test_grpc_helpers.py

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,10 @@ def test_create_channel_implicit(grpc_secure_channel, default, composite_creds_c
365365

366366
default.assert_called_once_with(scopes=None, default_scopes=None)
367367

368-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
368+
if grpc_helpers.HAS_GRPC_GCP:
369+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
370+
else:
371+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
369372

370373

371374
@mock.patch("google.auth.transport.grpc.AuthMetadataPlugin", autospec=True)
@@ -397,7 +400,10 @@ def test_create_channel_implicit_with_default_host(
397400
mock.sentinel.credentials, mock.sentinel.Request, default_host=default_host
398401
)
399402

400-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
403+
if grpc_helpers.HAS_GRPC_GCP:
404+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
405+
else:
406+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
401407

402408

403409
@mock.patch("grpc.composite_channel_credentials")
@@ -420,7 +426,11 @@ def test_create_channel_implicit_with_ssl_creds(
420426

421427
composite_creds_call.assert_called_once_with(ssl_creds, mock.ANY)
422428
composite_creds = composite_creds_call.return_value
423-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
429+
430+
if grpc_helpers.HAS_GRPC_GCP:
431+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
432+
else:
433+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
424434

425435

426436
@mock.patch("grpc.composite_channel_credentials")
@@ -442,7 +452,10 @@ def test_create_channel_implicit_with_scopes(
442452

443453
default.assert_called_once_with(scopes=["one", "two"], default_scopes=None)
444454

445-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
455+
if grpc_helpers.HAS_GRPC_GCP:
456+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
457+
else:
458+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
446459

447460

448461
@mock.patch("grpc.composite_channel_credentials")
@@ -464,7 +477,10 @@ def test_create_channel_implicit_with_default_scopes(
464477

465478
default.assert_called_once_with(scopes=None, default_scopes=["three", "four"])
466479

467-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
480+
if grpc_helpers.HAS_GRPC_GCP:
481+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
482+
else:
483+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
468484

469485

470486
def test_create_channel_explicit_with_duplicate_credentials():
@@ -492,7 +508,11 @@ def test_create_channel_explicit(grpc_secure_channel, auth_creds, composite_cred
492508
)
493509

494510
assert channel is grpc_secure_channel.return_value
495-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
511+
512+
if grpc_helpers.HAS_GRPC_GCP:
513+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
514+
else:
515+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
496516

497517

498518
@mock.patch("grpc.composite_channel_credentials")
@@ -512,7 +532,11 @@ def test_create_channel_explicit_scoped(grpc_secure_channel, composite_creds_cal
512532
credentials.with_scopes.assert_called_once_with(scopes, default_scopes=None)
513533

514534
assert channel is grpc_secure_channel.return_value
515-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
535+
536+
if grpc_helpers.HAS_GRPC_GCP:
537+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
538+
else:
539+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
516540

517541

518542
@mock.patch("grpc.composite_channel_credentials")
@@ -536,7 +560,11 @@ def test_create_channel_explicit_default_scopes(
536560
)
537561

538562
assert channel is grpc_secure_channel.return_value
539-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
563+
564+
if grpc_helpers.HAS_GRPC_GCP:
565+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
566+
else:
567+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
540568

541569

542570
@mock.patch("grpc.composite_channel_credentials")
@@ -558,7 +586,11 @@ def test_create_channel_explicit_with_quota_project(
558586
credentials.with_quota_project.assert_called_once_with("project-foo")
559587

560588
assert channel is grpc_secure_channel.return_value
561-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
589+
590+
if grpc_helpers.HAS_GRPC_GCP:
591+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
592+
else:
593+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
562594

563595

564596
@mock.patch("grpc.composite_channel_credentials")
@@ -583,7 +615,11 @@ def test_create_channel_with_credentials_file(
583615
)
584616

585617
assert channel is grpc_secure_channel.return_value
586-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
618+
619+
if grpc_helpers.HAS_GRPC_GCP:
620+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
621+
else:
622+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
587623

588624

589625
@mock.patch("grpc.composite_channel_credentials")
@@ -611,7 +647,11 @@ def test_create_channel_with_credentials_file_and_scopes(
611647
)
612648

613649
assert channel is grpc_secure_channel.return_value
614-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
650+
651+
if grpc_helpers.HAS_GRPC_GCP:
652+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
653+
else:
654+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
615655

616656

617657
@mock.patch("grpc.composite_channel_credentials")
@@ -639,11 +679,33 @@ def test_create_channel_with_credentials_file_and_default_scopes(
639679
)
640680

641681
assert channel is grpc_secure_channel.return_value
642-
grpc_secure_channel.assert_called_once_with(target, composite_creds)
682+
683+
if grpc_helpers.HAS_GRPC_GCP:
684+
grpc_secure_channel.assert_called_once_with(target, composite_creds, None)
685+
else:
686+
grpc_secure_channel.assert_called_once_with(target, composite_creds)
687+
688+
689+
@pytest.mark.skipif(
690+
not grpc_helpers.HAS_GRPC_GCP, reason="grpc_gcp module not available"
691+
)
692+
@mock.patch("grpc_gcp.secure_channel")
693+
def test_create_channel_with_grpc_gcp(grpc_gcp_secure_channel):
694+
target = "example.com:443"
695+
scopes = ["test_scope"]
696+
697+
credentials = mock.create_autospec(google.auth.credentials.Scoped, instance=True)
698+
credentials.requires_scopes = True
699+
700+
grpc_helpers.create_channel(target, credentials=credentials, scopes=scopes)
701+
grpc_gcp_secure_channel.assert_called()
702+
703+
credentials.with_scopes.assert_called_once_with(scopes, default_scopes=None)
643704

644705

706+
@pytest.mark.skipif(grpc_helpers.HAS_GRPC_GCP, reason="grpc_gcp module not available")
645707
@mock.patch("grpc.secure_channel")
646-
def test_create_channel(grpc_secure_channel):
708+
def test_create_channel_without_grpc_gcp(grpc_secure_channel):
647709
target = "example.com:443"
648710
scopes = ["test_scope"]
649711

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy