Skip to content

Commit d2a160d

Browse files
committed
feat(clients): allow non-dev API endpoint roots
Specifying an API endpoint root to a client used to imply that the endpoint in use was for dev, which would disable TLS and token bearer authorisation. This is not always a valid assumption, for example when manually specifying a locational endpoint for Google PubSub to target a specific region, as such endpoints are for production and should therefore use TLS and authorisation. Fix this by allowing manual configuration of the `api_is_dev` setting when using a non-dev root, whilst maintaining the old behaviour by default for backwards compatibility.
1 parent c70efc4 commit d2a160d

30 files changed

Lines changed: 491 additions & 137 deletions

auth/poetry.rest.lock

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ files = [
1313

1414
[[package]]
1515
name = "certifi"
16-
version = "2024.6.2"
16+
version = "2024.8.30"
1717
description = "Python package for providing Mozilla's CA Bundle."
1818
optional = false
1919
python-versions = ">=3.6"
2020
files = [
21-
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
22-
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
21+
{file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
22+
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
2323
]
2424

2525
[[package]]
@@ -353,21 +353,21 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
353353

354354
[[package]]
355355
name = "pytest"
356-
version = "8.2.2"
356+
version = "8.3.3"
357357
description = "pytest: simple powerful testing with Python"
358358
optional = false
359359
python-versions = ">=3.8"
360360
files = [
361-
{file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"},
362-
{file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"},
361+
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
362+
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
363363
]
364364

365365
[package.dependencies]
366366
colorama = {version = "*", markers = "sys_platform == \"win32\""}
367367
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
368368
iniconfig = "*"
369369
packaging = "*"
370-
pluggy = ">=1.5,<2.0"
370+
pluggy = ">=1.5,<2"
371371
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
372372

373373
[package.extras]
@@ -424,13 +424,13 @@ files = [
424424

425425
[[package]]
426426
name = "urllib3"
427-
version = "2.2.1"
427+
version = "2.2.2"
428428
description = "HTTP library with thread-safe connection pooling, file post, and more."
429429
optional = false
430430
python-versions = ">=3.8"
431431
files = [
432-
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
433-
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
432+
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
433+
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
434434
]
435435

436436
[package.extras]
@@ -442,4 +442,4 @@ zstd = ["zstandard (>=0.18.0)"]
442442
[metadata]
443443
lock-version = "2.0"
444444
python-versions = ">= 3.8, < 4.0"
445-
content-hash = "0a8e3c7f35afc47adf19cfc80379283f411511be97c5400c593f1e9d94ec1334"
445+
content-hash = "33d10c6c4fa764ec12e79a7cb93f22b67a92e4e174d364b1b47ad1bb411518ca"

auth/pyproject.rest.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "gcloud-rest-auth"
3-
version = "5.3.1"
3+
version = "5.3.2"
44
description = "Python Client for Google Cloud Auth"
55
readme = "README.rst"
66

@@ -30,8 +30,8 @@ pyjwt = ">= 1.5.3, < 3.0.0"
3030
requests = ">= 2.2.1, < 3.0.0"
3131

3232
[tool.poetry.group.dev.dependencies]
33-
pytest = "8.2.2"
34-
# pytest-asyncio = "0.23.7"
33+
pytest = "8.3.3"
34+
# pytest-asyncio = "0.23.8"
3535
pytest-mock = "3.14.0"
3636

3737
[[tool.poetry.source]]

bigquery/gcloud/aio/bigquery/bigquery.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,14 @@
2929
log = logging.getLogger(__name__)
3030

3131

32-
def init_api_root(api_root: Optional[str]) -> Tuple[bool, str]:
32+
def init_api_root(
33+
api_root: Optional[str], api_is_dev: Optional[bool],
34+
) -> Tuple[bool, str]:
3335
if api_root:
34-
return True, api_root
36+
if api_is_dev is None:
37+
# Assume a provided API root is dev unless otherwise specified
38+
api_is_dev = True
39+
return api_is_dev, api_root
3540

3641
host = os.environ.get('BIGQUERY_EMULATOR_HOST')
3742
if host:
@@ -69,9 +74,9 @@ def __init__(
6974
self, project: Optional[str] = None,
7075
service_file: Optional[Union[str, IO[AnyStr]]] = None,
7176
session: Optional[Session] = None, token: Optional[Token] = None,
72-
api_root: Optional[str] = None,
77+
api_root: Optional[str] = None, api_is_dev: Optional[bool] = None,
7378
) -> None:
74-
self._api_is_dev, self._api_root = init_api_root(api_root)
79+
self._api_is_dev, self._api_root = init_api_root(api_root, api_is_dev)
7580
self.session = AioSession(session)
7681
self.token = token or Token(
7782
service_file=service_file, scopes=SCOPES,

bigquery/poetry.rest.lock

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ files = [
1313

1414
[[package]]
1515
name = "certifi"
16-
version = "2024.6.2"
16+
version = "2024.8.30"
1717
description = "Python package for providing Mozilla's CA Bundle."
1818
optional = false
1919
python-versions = ">=3.6"
2020
files = [
21-
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
22-
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
21+
{file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
22+
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
2323
]
2424

2525
[[package]]
@@ -277,7 +277,7 @@ test = ["pytest (>=6)"]
277277

278278
[[package]]
279279
name = "gcloud-rest-auth"
280-
version = "5.3.1"
280+
version = "5.3.2"
281281
description = "Python Client for Google Cloud Auth"
282282
optional = false
283283
python-versions = ">= 3.8, < 4.0"
@@ -322,7 +322,7 @@ develop = false
322322

323323
[package.dependencies]
324324
gcloud-rest-auth = ">= 5.3.0, < 6.0.0"
325-
pyasn1-modules = ">= 0.2.1, < 0.4.1"
325+
pyasn1-modules = ">= 0.2.1, < 0.4.2"
326326
rsa = ">= 3.1.4, < 5.0.0"
327327

328328
[package.source]
@@ -432,21 +432,21 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
432432

433433
[[package]]
434434
name = "pytest"
435-
version = "8.2.2"
435+
version = "8.3.3"
436436
description = "pytest: simple powerful testing with Python"
437437
optional = false
438438
python-versions = ">=3.8"
439439
files = [
440-
{file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"},
441-
{file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"},
440+
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
441+
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
442442
]
443443

444444
[package.dependencies]
445445
colorama = {version = "*", markers = "sys_platform == \"win32\""}
446446
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
447447
iniconfig = "*"
448448
packaging = "*"
449-
pluggy = ">=1.5,<2.0"
449+
pluggy = ">=1.5,<2"
450450
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
451451

452452
[package.extras]
@@ -517,13 +517,13 @@ files = [
517517

518518
[[package]]
519519
name = "urllib3"
520-
version = "2.2.1"
520+
version = "2.2.2"
521521
description = "HTTP library with thread-safe connection pooling, file post, and more."
522522
optional = false
523523
python-versions = ">=3.8"
524524
files = [
525-
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
526-
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
525+
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
526+
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
527527
]
528528

529529
[package.extras]
@@ -535,4 +535,4 @@ zstd = ["zstandard (>=0.18.0)"]
535535
[metadata]
536536
lock-version = "2.0"
537537
python-versions = ">= 3.8, < 4.0"
538-
content-hash = "2b4c5e685ccbd1981c6304fba0d224993f96fd4e3e0cdc86327c06585f0edaa5"
538+
content-hash = "9dd0c655978fdba6dd4fa3f494140b57745f3af95747b85e0128720734150d49"

bigquery/pyproject.rest.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ gcloud-rest-auth = ">= 3.1.0, < 6.0.0"
2727
gcloud-rest-auth = { path = "../auth" }
2828
gcloud-rest-datastore = { path = "../datastore" }
2929
gcloud-rest-storage = { path = "../storage" }
30-
pytest = "8.2.2"
31-
# pytest-asyncio = "0.23.7"
30+
pytest = "8.3.3"
31+
# pytest-asyncio = "0.23.8"
3232
pytest-mock = "3.14.0"
3333

3434
[[tool.poetry.source]]

bigquery/tests/unit/bigquery_test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
from unittest.mock import AsyncMock
2+
3+
import pytest
14
from gcloud.aio.bigquery import Table
5+
from gcloud.aio.bigquery.bigquery import BigqueryBase
26

37

48
def test_make_insert_body():
@@ -52,3 +56,34 @@ def test_make_insert_body_defult_id_fn():
5256

5357
assert len(body['rows']) == 2
5458
assert all(r['insertId'] for r in body['rows'])
59+
60+
61+
# =========
62+
# client
63+
# =========
64+
@pytest.mark.asyncio
65+
async def test_client_api_is_dev():
66+
"""
67+
Test that the api_is_dev constructor parameter controls whether the
68+
Authorization header is set on requests
69+
"""
70+
api_root = 'https://foobar/v1'
71+
72+
# With no API root specified, assume API not dev, so auth header should be
73+
# set
74+
async with BigqueryBase(token=AsyncMock()) as bigquery:
75+
assert 'Authorization' in await bigquery.headers()
76+
# If API root set and not otherwise specified, assume API is dev, so auth
77+
# header should not be set
78+
async with BigqueryBase(api_root=api_root, token=AsyncMock()) as bigquery:
79+
assert 'Authorization' not in await bigquery.headers()
80+
# If API specified to be dev, auth header should not be set
81+
async with BigqueryBase(
82+
api_root=api_root, api_is_dev=True, token=AsyncMock(),
83+
) as bigquery:
84+
assert 'Authorization' not in await bigquery.headers()
85+
# If API specified to not be dev, auth header should be set
86+
async with BigqueryBase(
87+
api_root=api_root, api_is_dev=False, token=AsyncMock(),
88+
) as bigquery:
89+
assert 'Authorization' in await bigquery.headers()

datastore/gcloud/aio/datastore/datastore.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,14 @@
4444
LookUpResult = Dict[str, Union[str, List[Union[EntityResult, Key]]]]
4545

4646

47-
def init_api_root(api_root: Optional[str]) -> Tuple[bool, str]:
47+
def init_api_root(
48+
api_root: Optional[str], api_is_dev: Optional[bool],
49+
) -> Tuple[bool, str]:
4850
if api_root:
49-
return True, api_root
51+
if api_is_dev is None:
52+
# Assume a provided API root is dev unless otherwise specified
53+
api_is_dev = True
54+
return api_is_dev, api_root
5055

5156
host = os.environ.get('DATASTORE_EMULATOR_HOST')
5257
if host:
@@ -72,8 +77,9 @@ def __init__(
7277
service_file: Optional[Union[str, IO[AnyStr]]] = None,
7378
namespace: str = '', session: Optional[Session] = None,
7479
token: Optional[Token] = None, api_root: Optional[str] = None,
80+
api_is_dev: Optional[bool] = None,
7581
) -> None:
76-
self._api_is_dev, self._api_root = init_api_root(api_root)
82+
self._api_is_dev, self._api_root = init_api_root(api_root, api_is_dev)
7783
self.namespace = namespace
7884
self.session = AioSession(session)
7985
self.token = token or Token(

datastore/poetry.rest.lock

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ files = [
1313

1414
[[package]]
1515
name = "certifi"
16-
version = "2024.6.2"
16+
version = "2024.8.30"
1717
description = "Python package for providing Mozilla's CA Bundle."
1818
optional = false
1919
python-versions = ">=3.6"
2020
files = [
21-
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
22-
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
21+
{file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
22+
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
2323
]
2424

2525
[[package]]
@@ -277,7 +277,7 @@ test = ["pytest (>=6)"]
277277

278278
[[package]]
279279
name = "gcloud-rest-auth"
280-
version = "5.3.1"
280+
version = "5.3.2"
281281
description = "Python Client for Google Cloud Auth"
282282
optional = false
283283
python-versions = ">= 3.8, < 4.0"
@@ -306,7 +306,7 @@ develop = false
306306

307307
[package.dependencies]
308308
gcloud-rest-auth = ">= 5.3.0, < 6.0.0"
309-
pyasn1-modules = ">= 0.2.1, < 0.4.1"
309+
pyasn1-modules = ">= 0.2.1, < 0.4.2"
310310
rsa = ">= 3.1.4, < 5.0.0"
311311

312312
[package.source]
@@ -416,21 +416,21 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
416416

417417
[[package]]
418418
name = "pytest"
419-
version = "8.2.2"
419+
version = "8.3.3"
420420
description = "pytest: simple powerful testing with Python"
421421
optional = false
422422
python-versions = ">=3.8"
423423
files = [
424-
{file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"},
425-
{file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"},
424+
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
425+
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
426426
]
427427

428428
[package.dependencies]
429429
colorama = {version = "*", markers = "sys_platform == \"win32\""}
430430
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
431431
iniconfig = "*"
432432
packaging = "*"
433-
pluggy = ">=1.5,<2.0"
433+
pluggy = ">=1.5,<2"
434434
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
435435

436436
[package.extras]
@@ -501,13 +501,13 @@ files = [
501501

502502
[[package]]
503503
name = "urllib3"
504-
version = "2.2.1"
504+
version = "2.2.2"
505505
description = "HTTP library with thread-safe connection pooling, file post, and more."
506506
optional = false
507507
python-versions = ">=3.8"
508508
files = [
509-
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
510-
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
509+
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
510+
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
511511
]
512512

513513
[package.extras]
@@ -519,4 +519,4 @@ zstd = ["zstandard (>=0.18.0)"]
519519
[metadata]
520520
lock-version = "2.0"
521521
python-versions = ">= 3.8, < 4.0"
522-
content-hash = "2fbf77bdf723122dd0065a96d7a0e62515a7fba608415504d434f0096d3aa081"
522+
content-hash = "09644a57b223ca0ce1aad4d82ef50b4544c5424031798809458ae5866f9edd92"

datastore/pyproject.rest.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ gcloud-rest-auth = ">= 3.1.0, < 6.0.0"
2727
# aiohttp = "3.9.1"
2828
gcloud-rest-auth = { path = "../auth" }
2929
gcloud-rest-storage = { path = "../storage" }
30-
pytest = "8.2.2"
31-
# pytest-asyncio = "0.23.7"
30+
pytest = "8.3.3"
31+
# pytest-asyncio = "0.23.8"
3232
pytest-mock = "3.14.0"
3333

3434
[[tool.poetry.source]]

0 commit comments

Comments
 (0)