Content-Length: 1141621 | pFad | http://github.com/googleapis/google-cloud-python/commit/fc3b22e396a96424afe17700ddb06c52a31e8f13

7E Refactor 'client_info' support. (#7849) · googleapis/google-cloud-python@fc3b22e · GitHub
Skip to content

Commit fc3b22e

Browse files
authored
Refactor 'client_info' support. (#7849)
* Add 'user_agent' and 'extra_headers' properties to 'Connection'. Deprecate the 'USER_AGENT' and '_EXTRA_HEADERS' class-level attributes. * Add 'client_info' parameter to 'Connection' ctor. * Implement 'Connection.user_agent' via its '_client_info'. * Ensure 'X-Goog-API-Client' header is always passed. * Create/use non-GAPIC-specific 'ClientInfo' class FBO HTTP/JSON clients. Derive the existing GAPIC class from it.
1 parent 247244a commit fc3b22e

File tree

12 files changed

+413
-208
lines changed

12 files changed

+413
-208
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Copyright 2017 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+
# http://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+
15+
"""Helpers for providing client information.
16+
17+
Client information is used to send information about the calling client,
18+
such as the library and Python version, to API services.
19+
"""
20+
21+
import platform
22+
23+
import pkg_resources
24+
25+
_PY_VERSION = platform.python_version()
26+
_API_CORE_VERSION = pkg_resources.get_distribution("google-api-core").version
27+
28+
try:
29+
_GRPC_VERSION = pkg_resources.get_distribution("grpcio").version
30+
except pkg_resources.DistributionNotFound: # pragma: NO COVER
31+
_GRPC_VERSION = None
32+
33+
34+
class ClientInfo(object):
35+
"""Client information used to generate a user-agent for API calls.
36+
37+
This user-agent information is sent along with API calls to allow the
38+
receiving service to do analytics on which versions of Python and Google
39+
libraries are being used.
40+
41+
Args:
42+
python_version (str): The Python interpreter version, for example,
43+
``'2.7.13'``.
44+
grpc_version (Optional[str]): The gRPC library version.
45+
api_core_version (str): The google-api-core library version.
46+
gapic_version (Optional[str]): The sversion of gapic-generated client
47+
library, if the library was generated by gapic.
48+
client_library_version (Optional[str]): The version of the client
49+
library, generally used if the client library was not generated
50+
by gapic or if additional functionality was built on top of
51+
a gapic client library.
52+
user_agent (Optional[str]): Prefix to the user agent header. This is
53+
used to supply information such as application name or partner tool.
54+
Recommended format: ``application-or-tool-ID/major.minor.version``.
55+
"""
56+
57+
def __init__(
58+
self,
59+
python_version=_PY_VERSION,
60+
grpc_version=_GRPC_VERSION,
61+
api_core_version=_API_CORE_VERSION,
62+
gapic_version=None,
63+
client_library_version=None,
64+
user_agent=None,
65+
):
66+
self.python_version = python_version
67+
self.grpc_version = grpc_version
68+
self.api_core_version = api_core_version
69+
self.gapic_version = gapic_version
70+
self.client_library_version = client_library_version
71+
self.user_agent = user_agent
72+
73+
def to_user_agent(self):
74+
"""Returns the user-agent string for this client info."""
75+
76+
# Note: the order here is important as the internal metrics system
77+
# expects these items to be in specific locations.
78+
ua = ""
79+
80+
if self.user_agent is not None:
81+
ua += "{user_agent} "
82+
83+
ua += "gl-python/{python_version} "
84+
85+
if self.grpc_version is not None:
86+
ua += "grpc/{grpc_version} "
87+
88+
ua += "gax/{api_core_version} "
89+
90+
if self.gapic_version is not None:
91+
ua += "gapic/{gapic_version} "
92+
93+
if self.client_library_version is not None:
94+
ua += "gccl/{client_library_version} "
95+
96+
return ua.format(**self.__dict__).strip()

api_core/google/api_core/gapic_v1/client_info.py

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,13 @@
1818
such as the library and Python version, to API services.
1919
"""
2020

21-
import platform
21+
from google.api_core import client_info
2222

23-
import pkg_resources
24-
25-
_PY_VERSION = platform.python_version()
26-
_API_CORE_VERSION = pkg_resources.get_distribution("google-api-core").version
27-
28-
try:
29-
_GRPC_VERSION = pkg_resources.get_distribution("grpcio").version
30-
except pkg_resources.DistributionNotFound: # pragma: NO COVER
31-
_GRPC_VERSION = None
3223

3324
METRICS_METADATA_KEY = "x-goog-api-client"
3425

3526

36-
class ClientInfo(object):
27+
class ClientInfo(client_info.ClientInfo):
3728
"""Client information used to generate a user-agent for API calls.
3829
3930
This user-agent information is sent along with API calls to allow the
@@ -56,47 +47,6 @@ class ClientInfo(object):
5647
Recommended format: ``application-or-tool-ID/major.minor.version``.
5748
"""
5849

59-
def __init__(
60-
self,
61-
python_version=_PY_VERSION,
62-
grpc_version=_GRPC_VERSION,
63-
api_core_version=_API_CORE_VERSION,
64-
gapic_version=None,
65-
client_library_version=None,
66-
user_agent=None,
67-
):
68-
self.python_version = python_version
69-
self.grpc_version = grpc_version
70-
self.api_core_version = api_core_version
71-
self.gapic_version = gapic_version
72-
self.client_library_version = client_library_version
73-
self.user_agent = user_agent
74-
75-
def to_user_agent(self):
76-
"""Returns the user-agent string for this client info."""
77-
78-
# Note: the order here is important as the internal metrics system
79-
# expects these items to be in specific locations.
80-
ua = ""
81-
82-
if self.user_agent is not None:
83-
ua += "{user_agent} "
84-
85-
ua += "gl-python/{python_version} "
86-
87-
if self.grpc_version is not None:
88-
ua += "grpc/{grpc_version} "
89-
90-
ua += "gax/{api_core_version} "
91-
92-
if self.gapic_version is not None:
93-
ua += "gapic/{gapic_version} "
94-
95-
if self.client_library_version is not None:
96-
ua += "gccl/{client_library_version} "
97-
98-
return ua.format(**self.__dict__).strip()
99-
10050
def to_grpc_metadata(self):
10151
"""Returns the gRPC metadata for this client info."""
10252
return (METRICS_METADATA_KEY, self.to_user_agent())

api_core/tests/unit/gapic/test_client_info.py

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,59 +16,6 @@
1616
from google.api_core.gapic_v1 import client_info
1717

1818

19-
def test_constructor_defaults():
20-
info = client_info.ClientInfo()
21-
22-
assert info.python_version is not None
23-
assert info.grpc_version is not None
24-
assert info.api_core_version is not None
25-
assert info.gapic_version is None
26-
assert info.client_library_version is None
27-
28-
29-
def test_constructor_options():
30-
info = client_info.ClientInfo(
31-
python_version="1",
32-
grpc_version="2",
33-
api_core_version="3",
34-
gapic_version="4",
35-
client_library_version="5",
36-
user_agent="6"
37-
)
38-
39-
assert info.python_version == "1"
40-
assert info.grpc_version == "2"
41-
assert info.api_core_version == "3"
42-
assert info.gapic_version == "4"
43-
assert info.client_library_version == "5"
44-
assert info.user_agent == "6"
45-
46-
47-
def test_to_user_agent_minimal():
48-
info = client_info.ClientInfo(
49-
python_version="1", api_core_version="2", grpc_version=None
50-
)
51-
52-
user_agent = info.to_user_agent()
53-
54-
assert user_agent == "gl-python/1 gax/2"
55-
56-
57-
def test_to_user_agent_full():
58-
info = client_info.ClientInfo(
59-
python_version="1",
60-
grpc_version="2",
61-
api_core_version="3",
62-
gapic_version="4",
63-
client_library_version="5",
64-
user_agent="app-name/1.0",
65-
)
66-
67-
user_agent = info.to_user_agent()
68-
69-
assert user_agent == "app-name/1.0 gl-python/1 grpc/2 gax/3 gapic/4 gccl/5"
70-
71-
7219
def test_to_grpc_metadata():
7320
info = client_info.ClientInfo()
7421

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Copyright 2017 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+
# http://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+
15+
16+
from google.api_core import client_info
17+
18+
19+
def test_constructor_defaults():
20+
info = client_info.ClientInfo()
21+
22+
assert info.python_version is not None
23+
assert info.grpc_version is not None
24+
assert info.api_core_version is not None
25+
assert info.gapic_version is None
26+
assert info.client_library_version is None
27+
28+
29+
def test_constructor_options():
30+
info = client_info.ClientInfo(
31+
python_version="1",
32+
grpc_version="2",
33+
api_core_version="3",
34+
gapic_version="4",
35+
client_library_version="5",
36+
user_agent="6"
37+
)
38+
39+
assert info.python_version == "1"
40+
assert info.grpc_version == "2"
41+
assert info.api_core_version == "3"
42+
assert info.gapic_version == "4"
43+
assert info.client_library_version == "5"
44+
assert info.user_agent == "6"
45+
46+
47+
def test_to_user_agent_minimal():
48+
info = client_info.ClientInfo(
49+
python_version="1", api_core_version="2", grpc_version=None
50+
)
51+
52+
user_agent = info.to_user_agent()
53+
54+
assert user_agent == "gl-python/1 gax/2"
55+
56+
57+
def test_to_user_agent_full():
58+
info = client_info.ClientInfo(
59+
python_version="1",
60+
grpc_version="2",
61+
api_core_version="3",
62+
gapic_version="4",
63+
client_library_version="5",
64+
user_agent="app-name/1.0",
65+
)
66+
67+
user_agent = info.to_user_agent()
68+
69+
assert user_agent == "app-name/1.0 gl-python/1 grpc/2 gax/3 gapic/4 gccl/5"

bigquery/google/cloud/bigquery/_http.py

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
"""Create / interact with Google BigQuery connections."""
1616

17-
import google.api_core.gapic_v1.client_info
1817
from google.cloud import _http
1918

2019
from google.cloud.bigquery import __version__
@@ -25,20 +24,16 @@ class Connection(_http.JSONConnection):
2524
2625
:type client: :class:`~google.cloud.bigquery.client.Client`
2726
:param client: The client that owns the current connection.
27+
28+
:type client_info: :class:`~google.api_core.client_info.ClientInfo`
29+
:param client_info: (Optional) instance used to generate user agent.
2830
"""
2931

3032
def __init__(self, client, client_info=None):
31-
super(Connection, self).__init__(client)
33+
super(Connection, self).__init__(client, client_info)
3234

33-
if client_info is None:
34-
client_info = google.api_core.gapic_v1.client_info.ClientInfo(
35-
gapic_version=__version__, client_library_version=__version__
36-
)
37-
else:
38-
client_info.gapic_version = __version__
39-
client_info.client_library_version = __version__
40-
self._client_info = client_info
41-
self._extra_headers = {}
35+
self._client_info.gapic_version = __version__
36+
self._client_info.client_library_version = __version__
4237

4338
API_BASE_URL = "https://www.googleapis.com"
4439
"""The base of the API call URL."""
@@ -48,22 +43,3 @@ def __init__(self, client, client_info=None):
4843

4944
API_URL_TEMPLATE = "{api_base_url}/bigquery/{api_version}{path}"
5045
"""A template for the URL of a particular API call."""
51-
52-
@property
53-
def USER_AGENT(self):
54-
return self._client_info.to_user_agent()
55-
56-
@USER_AGENT.setter
57-
def USER_AGENT(self, value):
58-
self._client_info.user_agent = value
59-
60-
@property
61-
def _EXTRA_HEADERS(self):
62-
self._extra_headers[
63-
_http.CLIENT_INFO_HEADER
64-
] = self._client_info.to_user_agent()
65-
return self._extra_headers
66-
67-
@_EXTRA_HEADERS.setter
68-
def _EXTRA_HEADERS(self, value):
69-
self._extra_headers = value

bigquery/google/cloud/bigquery/client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class Client(ClientWithProject):
128128
default_query_job_config (google.cloud.bigquery.job.QueryJobConfig):
129129
(Optional) Default ``QueryJobConfig``.
130130
Will be merged into job configs passed into the ``query`` method.
131-
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
131+
client_info (google.api_core.client_info.ClientInfo):
132132
The client info used to send a user-agent string along with API
133133
requests. If ``None``, then default info will be used. Generally,
134134
you only need to set this if you're developing your own library
@@ -1363,7 +1363,7 @@ def _initiate_resumable_upload(self, stream, metadata, num_retries):
13631363
"""
13641364
chunk_size = _DEFAULT_CHUNKSIZE
13651365
transport = self._http
1366-
headers = _get_upload_headers(self._connection.USER_AGENT)
1366+
headers = _get_upload_headers(self._connection.user_agent)
13671367
upload_url = _RESUMABLE_URL_TEMPLATE.format(project=self.project)
13681368
# TODO: modify ResumableUpload to take a retry.Retry object
13691369
# that it can use for the initial RPC.
@@ -1409,7 +1409,7 @@ def _do_multipart_upload(self, stream, metadata, size, num_retries):
14091409
msg = _READ_LESS_THAN_SIZE.format(size, len(data))
14101410
raise ValueError(msg)
14111411

1412-
headers = _get_upload_headers(self._connection.USER_AGENT)
1412+
headers = _get_upload_headers(self._connection.user_agent)
14131413

14141414
upload_url = _MULTIPART_URL_TEMPLATE.format(project=self.project)
14151415
upload = MultipartUpload(upload_url, headers=headers)

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/googleapis/google-cloud-python/commit/fc3b22e396a96424afe17700ddb06c52a31e8f13

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy