Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-google-cloud-core for
openSUSE:Factory checked in at 2021-04-14 10:10:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-google-cloud-core (Old)
and /work/SRC/openSUSE:Factory/.python-google-cloud-core.new.2401 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-cloud-core"
Wed Apr 14 10:10:55 2021 rev:8 rq:884874 version:1.6.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-google-cloud-core/python-google-cloud-core.changes
2020-04-21 13:10:49.748831654 +0200
+++
/work/SRC/openSUSE:Factory/.python-google-cloud-core.new.2401/python-google-cloud-core.changes
2021-04-14 10:11:23.241535054 +0200
@@ -1,0 +2,13 @@
+Tue Apr 6 07:45:12 UTC 2021 - Dirk M??ller <[email protected]>
+
+- update to 1.6.0:
+ * add mtls support
+ * infer project from explicit service account creds
+ * add support for Python 3.9, drop support for Python 3.5
+ * require six>=1.12.0 and google-api-core>=1.21.
+ * avoid using 'pkg_resources' to determine version
+ * handle query_params tuples in JSONConnection.build_api_url
+ * add quota_project, credentials file, and scopes options
+ * add support for Python 3.8
+
+-------------------------------------------------------------------
Old:
----
google-cloud-core-1.3.0.tar.gz
New:
----
google-cloud-core-1.6.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-google-cloud-core.spec ++++++
--- /var/tmp/diff_new_pack.nwPd1h/_old 2021-04-14 10:11:23.817536026 +0200
+++ /var/tmp/diff_new_pack.nwPd1h/_new 2021-04-14 10:11:23.821536033 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-google-cloud-core
#
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,21 +19,24 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%bcond_without python2
Name: python-google-cloud-core
-Version: 1.3.0
+Version: 1.6.0
Release: 0
Summary: Google Cloud API client core library
License: Apache-2.0
Group: Development/Languages/Python
-URL: https://github.com/GoogleCloudPlatform/google-cloud-python
+URL: https://github.com/googleapis/python-cloud-core
Source:
https://files.pythonhosted.org/packages/source/g/google-cloud-core/google-cloud-core-%{version}.tar.gz
-BuildRequires: %{python_module google-api-core >= 1.16.0}
+BuildRequires: %{python_module google-api-core >= 1.21.0}
+BuildRequires: %{python_module google-auth >= 1.24.0}
BuildRequires: %{python_module grpcio >= 1.8.2}
BuildRequires: %{python_module mock}
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python-google-api-core >= 1.16.0
+Requires: python-google-api-core >= 1.21.0
+Requires: python-google-auth >= 1.24.0
+Requires: python-six >= 1.12.0
Recommends: python-grpcio >= 1.8.2
BuildArch: noarch
%if %{with python2}
++++++ google-cloud-core-1.3.0.tar.gz -> google-cloud-core-1.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/MANIFEST.in
new/google-cloud-core-1.6.0/MANIFEST.in
--- old/google-cloud-core-1.3.0/MANIFEST.in 2020-01-31 22:59:39.000000000
+0100
+++ new/google-cloud-core-1.6.0/MANIFEST.in 2021-02-06 02:19:50.000000000
+0100
@@ -1,3 +1,25 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Generated by synthtool. DO NOT EDIT!
include README.rst LICENSE
+recursive-include google *.json *.proto
recursive-include tests *
-global-exclude *.pyc __pycache__
+global-exclude *.py[co]
+global-exclude __pycache__
+
+# Exclude scripts for samples readmegen
+prune scripts/readme-gen
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/PKG-INFO
new/google-cloud-core-1.6.0/PKG-INFO
--- old/google-cloud-core-1.3.0/PKG-INFO 2020-01-31 23:02:20.810099000
+0100
+++ new/google-cloud-core-1.6.0/PKG-INFO 2021-02-06 02:23:12.442483000
+0100
@@ -1,15 +1,15 @@
Metadata-Version: 2.1
Name: google-cloud-core
-Version: 1.3.0
+Version: 1.6.0
Summary: Google Cloud API client core library
-Home-page: https://github.com/GoogleCloudPlatform/google-cloud-python
+Home-page: https://github.com/googleapis/python-cloud-core
Author: Google LLC
Author-email: [email protected]
License: Apache 2.0
Description: Core Helpers for Google Cloud Python Client Library
===================================================
- |pypi| |versions|
+ |pypi| |versions|
This library is not meant to stand-alone. Instead it defines
common helpers (e.g. base ``Client`` classes) used by all of the
@@ -40,24 +40,25 @@
Supported Python Versions
-------------------------
- Python >= 3.5
+ Python >= 3.6
Deprecated Python Versions
--------------------------
Python == 2.7. Python 2.7 support will be removed on January 1, 2020.
Platform: Posix; MacOS X; Windows
-Classifier: Development Status :: 4 - Beta
+Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet
-Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
+Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*
Provides-Extra: grpc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/README.rst
new/google-cloud-core-1.6.0/README.rst
--- old/google-cloud-core-1.3.0/README.rst 2020-01-31 22:59:39.000000000
+0100
+++ new/google-cloud-core-1.6.0/README.rst 2021-02-06 02:19:50.000000000
+0100
@@ -1,7 +1,7 @@
Core Helpers for Google Cloud Python Client Library
===================================================
-|pypi| |versions|
+|pypi| |versions|
This library is not meant to stand-alone. Instead it defines
common helpers (e.g. base ``Client`` classes) used by all of the
@@ -32,7 +32,7 @@
Supported Python Versions
-------------------------
-Python >= 3.5
+Python >= 3.6
Deprecated Python Versions
--------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/google/cloud/_http.py
new/google-cloud-core-1.6.0/google/cloud/_http.py
--- old/google-cloud-core-1.3.0/google/cloud/_http.py 2020-01-31
22:59:39.000000000 +0100
+++ new/google-cloud-core-1.6.0/google/cloud/_http.py 2021-02-06
02:19:50.000000000 +0100
@@ -14,22 +14,28 @@
"""Shared implementation of connections to API servers."""
+import collections
+try:
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
import json
+import os
import platform
import warnings
-from pkg_resources import get_distribution
from six.moves.urllib.parse import urlencode
from google.api_core.client_info import ClientInfo
from google.cloud import exceptions
+from google.cloud import version
API_BASE_URL = "https://www.googleapis.com"
"""The base of the API call URL."""
DEFAULT_USER_AGENT = "gcloud-python/{0}".format(
- get_distribution("google-cloud-core").version
+ version.__version__
)
"""The user agent for google-cloud-python requests."""
@@ -171,12 +177,56 @@
API_BASE_URL = None
"""The base of the API call URL."""
+ API_BASE_MTLS_URL = None
+ """The base of the API call URL for mutual TLS."""
+
+ ALLOW_AUTO_SWITCH_TO_MTLS_URL = False
+ """Indicates if auto switch to mTLS url is allowed."""
+
API_VERSION = None
"""The version of the API, used in building the API call's URL."""
API_URL_TEMPLATE = None
"""A template for the URL of a particular API call."""
+ def get_api_base_url_for_mtls(self, api_base_url=None):
+ """Return the api base url for mutual TLS.
+
+ Typically, you shouldn't need to use this method.
+
+ The logic is as follows:
+
+ If `api_base_url` is provided, just return this value; otherwise, the
+ return value depends `GOOGLE_API_USE_MTLS_ENDPOINT` environment
variable
+ value.
+
+ If the environment variable value is "always", return
`API_BASE_MTLS_URL`.
+ If the environment variable value is "never", return `API_BASE_URL`.
+ Otherwise, if `ALLOW_AUTO_SWITCH_TO_MTLS_URL` is True and the
underlying
+ http is mTLS, then return `API_BASE_MTLS_URL`; otherwise return
`API_BASE_URL`.
+
+ :type api_base_url: str
+ :param api_base_url: User provided api base url. It takes precedence
over
+ `API_BASE_URL` and `API_BASE_MTLS_URL`.
+
+ :rtype: str
+ :returns: The api base url used for mTLS.
+ """
+ if api_base_url:
+ return api_base_url
+
+ env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
+ if env == "always":
+ url_to_use = self.API_BASE_MTLS_URL
+ elif env == "never":
+ url_to_use = self.API_BASE_URL
+ else:
+ if self.ALLOW_AUTO_SWITCH_TO_MTLS_URL:
+ url_to_use = self.API_BASE_MTLS_URL if self.http.is_mtls else
self.API_BASE_URL
+ else:
+ url_to_use = self.API_BASE_URL
+ return url_to_use
+
def build_api_url(
self, path, query_params=None, api_base_url=None, api_version=None
):
@@ -205,14 +255,24 @@
:returns: The URL assembled from the pieces provided.
"""
url = self.API_URL_TEMPLATE.format(
- api_base_url=(api_base_url or self.API_BASE_URL),
+ api_base_url=self.get_api_base_url_for_mtls(api_base_url),
api_version=(api_version or self.API_VERSION),
path=path,
)
query_params = query_params or {}
- if query_params:
- url += "?" + urlencode(query_params, doseq=True)
+
+ if isinstance(query_params, collections_abc.Mapping):
+ query_params = query_params.copy()
+ else:
+ query_params_dict = collections.defaultdict(list)
+ for key, value in query_params:
+ query_params_dict[key].append(value)
+ query_params = query_params_dict
+
+ query_params.setdefault("prettyPrint", "false")
+
+ url += "?" + urlencode(query_params, doseq=True)
return url
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/google/cloud/client.py
new/google-cloud-core-1.6.0/google/cloud/client.py
--- old/google-cloud-core-1.3.0/google/cloud/client.py 2020-01-31
22:59:39.000000000 +0100
+++ new/google-cloud-core-1.6.0/google/cloud/client.py 2021-02-06
02:19:50.000000000 +0100
@@ -16,11 +16,15 @@
import io
import json
+import os
from pickle import PicklingError
import six
+import google.api_core.client_options
+import google.api_core.exceptions
import google.auth
+from google.auth import environment_vars
import google.auth.credentials
import google.auth.transport.requests
from google.cloud._helpers import _determine_default_project
@@ -102,6 +106,8 @@
(Optional) The OAuth2 Credentials to use for this client. If not
passed (and if no ``_http`` object is passed), falls back to the
default inferred from the environment.
+ client_options (google.api_core.client_options.ClientOptions):
+ (Optional) Custom options for the client.
_http (requests.Session):
(Optional) HTTP object to make requests. Can be any object that
defines ``request()`` with the same interface as
@@ -123,17 +129,37 @@
Needs to be set by subclasses.
"""
- def __init__(self, credentials=None, _http=None):
- if credentials is not None and not isinstance(
- credentials, google.auth.credentials.Credentials
- ):
+ def __init__(self, credentials=None, _http=None, client_options=None):
+ if isinstance(client_options, dict):
+ client_options =
google.api_core.client_options.from_dict(client_options)
+ if client_options is None:
+ client_options = google.api_core.client_options.ClientOptions()
+
+ if credentials and client_options.credentials_file:
+ raise google.api_core.exceptions.DuplicateCredentialArgs(
+ "'credentials' and 'client_options.credentials_file' are
mutually exclusive.")
+
+ if credentials and not isinstance(credentials,
google.auth.credentials.Credentials):
raise ValueError(_GOOGLE_AUTH_CREDENTIALS_HELP)
- if credentials is None and _http is None:
- credentials, _ = google.auth.default()
+
+ scopes = client_options.scopes or self.SCOPE
+
+ # if no http is provided, credentials must exist
+ if not _http and credentials is None:
+ if client_options.credentials_file:
+ credentials, _ = google.auth.load_credentials_from_file(
+ client_options.credentials_file, scopes=scopes)
+ else:
+ credentials, _ = google.auth.default(scopes=scopes)
+
self._credentials = google.auth.credentials.with_scopes_if_required(
- credentials, self.SCOPE
- )
+ credentials, scopes=scopes)
+
+ if client_options.quota_project_id:
+ self._credentials =
self._credentials.with_quota_project(client_options.quota_project_id)
+
self._http_internal = _http
+ self._client_cert_source = client_options.client_cert_source
def __getstate__(self):
"""Explicitly state that clients are not pickleable."""
@@ -158,6 +184,7 @@
self._credentials,
refresh_timeout=_CREDENTIALS_REFRESH_TIMEOUT,
)
+
self._http_internal.configure_mtls_channel(self._client_cert_source)
return self._http_internal
@@ -165,26 +192,50 @@
"""Mixin to allow setting the project on the client.
:type project: str
- :param project: the project which the client acts on behalf of. If not
- passed falls back to the default inferred from the
- environment.
+ :param project:
+ (Optional) the project which the client acts on behalf of. If not
+ passed, falls back to the default inferred from the environment.
+
+ :type credentials: :class:`google.auth.credentials.Credentials`
+ :param credentials:
+ (Optional) credentials used to discover a project, if not passed.
:raises: :class:`EnvironmentError` if the project is neither passed in nor
- set in the environment. :class:`ValueError` if the project value
- is invalid.
+ set on the credentials or in the environment. :class:`ValueError`
+ if the project value is invalid.
"""
- def __init__(self, project=None):
- project = self._determine_default(project)
+ def __init__(self, project=None, credentials=None):
+ # This test duplicates the one from `google.auth.default`, but earlier,
+ # for backward compatibility: we want the environment variable to
+ # override any project set on the credentials. See:
+ # https://github.com/googleapis/python-cloud-core/issues/27
+ if project is None:
+ project = os.getenv(
+ environment_vars.PROJECT,
+ os.getenv(environment_vars.LEGACY_PROJECT),
+ )
+
+ # Project set on explicit credentials overrides discovery from
+ # SDK / GAE / GCE.
+ if project is None and credentials is not None:
+ project = getattr(credentials, "project_id", None)
+
+ if project is None:
+ project = self._determine_default(project)
+
if project is None:
raise EnvironmentError(
"Project was not passed and could not be "
"determined from the environment."
)
+
if isinstance(project, six.binary_type):
project = project.decode("utf-8")
+
if not isinstance(project, six.string_types):
raise ValueError("Project must be a string.")
+
self.project = project
@staticmethod
@@ -222,6 +273,6 @@
_SET_PROJECT = True # Used by from_service_account_json()
- def __init__(self, project=None, credentials=None, _http=None):
- _ClientProjectMixin.__init__(self, project=project)
- Client.__init__(self, credentials=credentials, _http=_http)
+ def __init__(self, project=None, credentials=None, client_options=None,
_http=None):
+ _ClientProjectMixin.__init__(self, project=project,
credentials=credentials)
+ Client.__init__(self, credentials=credentials,
client_options=client_options, _http=_http)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/google/cloud/version.py
new/google-cloud-core-1.6.0/google/cloud/version.py
--- old/google-cloud-core-1.3.0/google/cloud/version.py 1970-01-01
01:00:00.000000000 +0100
+++ new/google-cloud-core-1.6.0/google/cloud/version.py 2021-02-06
02:19:50.000000000 +0100
@@ -0,0 +1,15 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+__version__ = "1.6.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-cloud-core-1.3.0/google_cloud_core.egg-info/PKG-INFO
new/google-cloud-core-1.6.0/google_cloud_core.egg-info/PKG-INFO
--- old/google-cloud-core-1.3.0/google_cloud_core.egg-info/PKG-INFO
2020-01-31 23:02:20.000000000 +0100
+++ new/google-cloud-core-1.6.0/google_cloud_core.egg-info/PKG-INFO
2021-02-06 02:23:12.000000000 +0100
@@ -1,15 +1,15 @@
Metadata-Version: 2.1
Name: google-cloud-core
-Version: 1.3.0
+Version: 1.6.0
Summary: Google Cloud API client core library
-Home-page: https://github.com/GoogleCloudPlatform/google-cloud-python
+Home-page: https://github.com/googleapis/python-cloud-core
Author: Google LLC
Author-email: [email protected]
License: Apache 2.0
Description: Core Helpers for Google Cloud Python Client Library
===================================================
- |pypi| |versions|
+ |pypi| |versions|
This library is not meant to stand-alone. Instead it defines
common helpers (e.g. base ``Client`` classes) used by all of the
@@ -40,24 +40,25 @@
Supported Python Versions
-------------------------
- Python >= 3.5
+ Python >= 3.6
Deprecated Python Versions
--------------------------
Python == 2.7. Python 2.7 support will be removed on January 1, 2020.
Platform: Posix; MacOS X; Windows
-Classifier: Development Status :: 4 - Beta
+Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet
-Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
+Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*
Provides-Extra: grpc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-cloud-core-1.3.0/google_cloud_core.egg-info/SOURCES.txt
new/google-cloud-core-1.6.0/google_cloud_core.egg-info/SOURCES.txt
--- old/google-cloud-core-1.3.0/google_cloud_core.egg-info/SOURCES.txt
2020-01-31 23:02:20.000000000 +0100
+++ new/google-cloud-core-1.6.0/google_cloud_core.egg-info/SOURCES.txt
2021-02-06 02:23:12.000000000 +0100
@@ -13,6 +13,7 @@
google/cloud/exceptions.py
google/cloud/obsolete.py
google/cloud/operation.py
+google/cloud/version.py
google_cloud_core.egg-info/PKG-INFO
google_cloud_core.egg-info/SOURCES.txt
google_cloud_core.egg-info/dependency_links.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-cloud-core-1.3.0/google_cloud_core.egg-info/requires.txt
new/google-cloud-core-1.6.0/google_cloud_core.egg-info/requires.txt
--- old/google-cloud-core-1.3.0/google_cloud_core.egg-info/requires.txt
2020-01-31 23:02:20.000000000 +0100
+++ new/google-cloud-core-1.6.0/google_cloud_core.egg-info/requires.txt
2021-02-06 02:23:12.000000000 +0100
@@ -1,4 +1,6 @@
-google-api-core<2.0.0dev,>=1.16.0
+google-api-core<2.0.0dev,>=1.21.0
+google-auth<2.0dev,>=1.24.0
+six>=1.12.0
[grpc]
grpcio<2.0dev,>=1.8.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/setup.py
new/google-cloud-core-1.6.0/setup.py
--- old/google-cloud-core-1.3.0/setup.py 2020-01-31 22:59:39.000000000
+0100
+++ new/google-cloud-core-1.6.0/setup.py 2021-02-06 02:19:50.000000000
+0100
@@ -22,13 +22,18 @@
name = "google-cloud-core"
description = "Google Cloud API client core library"
-version = "1.3.0"
# Should be one of:
# 'Development Status :: 3 - Alpha'
# 'Development Status :: 4 - Beta'
# 'Development Status :: 5 - Production/Stable'
-release_status = "Development Status :: 4 - Beta"
-dependencies = ["google-api-core >= 1.16.0, < 2.0.0dev"]
+release_status = "Development Status :: 5 - Production/Stable"
+dependencies = [
+ "google-api-core >= 1.21.0, < 2.0.0dev",
+ "google-auth >= 1.24.0, < 2.0dev",
+ # Support six==1.12.0 due to App Engine standard runtime.
+ # https://github.com/googleapis/python-cloud-core/issues/45
+ "six >=1.12.0",
+]
extras = {"grpc": "grpcio >= 1.8.2, < 2.0dev"}
@@ -36,6 +41,11 @@
package_root = os.path.abspath(os.path.dirname(__file__))
+version = {}
+with open(os.path.join(package_root, "google/cloud/version.py")) as fp:
+ exec(fp.read(), version)
+version = version["__version__"]
+
readme_filename = os.path.join(package_root, "README.rst")
with io.open(readme_filename, encoding="utf-8") as readme_file:
readme = readme_file.read()
@@ -60,7 +70,7 @@
author="Google LLC",
author_email="[email protected]",
license="Apache 2.0",
- url="https://github.com/GoogleCloudPlatform/google-cloud-python",
+ url="https://github.com/googleapis/python-cloud-core",
classifiers=[
release_status,
"Intended Audience :: Developers",
@@ -69,9 +79,10 @@
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
- 'Programming Language :: Python :: 3.7',
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
"Operating System :: OS Independent",
"Topic :: Internet",
],
@@ -80,7 +91,7 @@
namespace_packages=namespaces,
install_requires=dependencies,
extras_require=extras,
- python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
+ python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*",
include_package_data=True,
zip_safe=False,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/tests/unit/test__http.py
new/google-cloud-core-1.6.0/tests/unit/test__http.py
--- old/google-cloud-core-1.3.0/tests/unit/test__http.py 2020-01-31
22:59:39.000000000 +0100
+++ new/google-cloud-core-1.6.0/tests/unit/test__http.py 2021-02-06
02:19:50.000000000 +0100
@@ -13,6 +13,7 @@
# limitations under the License.
import json
+import os
import unittest
import warnings
@@ -165,6 +166,7 @@
class MockConnection(self._get_target_class()):
API_URL_TEMPLATE = "{api_base_url}/mock/{api_version}{path}"
API_BASE_URL = "http://mock"
+ API_BASE_MTLS_URL = "https://mock.mtls"
API_VERSION = "vMOCK"
return MockConnection(*args, **kw)
@@ -184,9 +186,16 @@
client = object()
conn = self._make_mock_one(client)
# Intended to emulate self.mock_template
- URI = "/".join([conn.API_BASE_URL, "mock", conn.API_VERSION, "foo"])
+ URI = "/".join([conn.API_BASE_URL, "mock", conn.API_VERSION,
"foo?prettyPrint=false"])
self.assertEqual(conn.build_api_url("/foo"), URI)
+ def test_build_api_url_w_pretty_print_query_params(self):
+ client = object()
+ conn = self._make_mock_one(client)
+ uri = conn.build_api_url("/foo", {"prettyPrint": "true"})
+ URI = "/".join([conn.API_BASE_URL, "mock", conn.API_VERSION,
"foo?prettyPrint=true"])
+ self.assertEqual(uri, URI)
+
def test_build_api_url_w_extra_query_params(self):
from six.moves.urllib.parse import parse_qs
from six.moves.urllib.parse import urlsplit
@@ -203,6 +212,69 @@
parms = dict(parse_qs(qs))
self.assertEqual(parms["bar"], ["baz"])
self.assertEqual(parms["qux"], ["quux", "corge"])
+ self.assertEqual(parms["prettyPrint"], ["false"])
+
+ def test_build_api_url_w_extra_query_params_tuples(self):
+ from six.moves.urllib.parse import parse_qs
+ from six.moves.urllib.parse import urlsplit
+
+ client = object()
+ conn = self._make_mock_one(client)
+ uri = conn.build_api_url("/foo", [("bar", "baz"), ("qux", "quux"),
("qux", "corge")])
+
+ scheme, netloc, path, qs, _ = urlsplit(uri)
+ self.assertEqual("%s://%s" % (scheme, netloc), conn.API_BASE_URL)
+ # Intended to emulate mock_template
+ PATH = "/".join(["", "mock", conn.API_VERSION, "foo"])
+ self.assertEqual(path, PATH)
+ parms = dict(parse_qs(qs))
+ self.assertEqual(parms["bar"], ["baz"])
+ self.assertEqual(parms["qux"], ["quux", "corge"])
+ self.assertEqual(parms["prettyPrint"], ["false"])
+
+ def test_get_api_base_url_for_mtls_w_api_base_url(self):
+ client = object()
+ conn = self._make_mock_one(client)
+ uri = conn.get_api_base_url_for_mtls(api_base_url="http://foo")
+ self.assertEqual(uri, "http://foo")
+
+ def test_get_api_base_url_for_mtls_env_always(self):
+ client = object()
+ conn = self._make_mock_one(client)
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT":
"always"}):
+ uri = conn.get_api_base_url_for_mtls()
+ self.assertEqual(uri, "https://mock.mtls")
+
+ def test_get_api_base_url_for_mtls_env_never(self):
+ client = object()
+ conn = self._make_mock_one(client)
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT":
"never"}):
+ uri = conn.get_api_base_url_for_mtls()
+ self.assertEqual(uri, "http://mock")
+
+ def test_get_api_base_url_for_mtls_env_auto(self):
+ client = mock.Mock()
+ client._http = mock.Mock()
+ client._http.is_mtls = False
+ conn = self._make_mock_one(client)
+
+ # ALLOW_AUTO_SWITCH_TO_MTLS_URL is False, so use regular endpoint.
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT":
"auto"}):
+ uri = conn.get_api_base_url_for_mtls()
+ self.assertEqual(uri, "http://mock")
+
+ # ALLOW_AUTO_SWITCH_TO_MTLS_URL is True, so now endpoint dependes
+ # on client._http.is_mtls
+ conn.ALLOW_AUTO_SWITCH_TO_MTLS_URL = True
+
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT":
"auto"}):
+ uri = conn.get_api_base_url_for_mtls()
+ self.assertEqual(uri, "http://mock")
+
+ client._http.is_mtls = True
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT":
"auto"}):
+ uri = conn.get_api_base_url_for_mtls()
+ self.assertEqual(uri, "https://mock.mtls")
def test__make_request_no_data_no_content_type_no_headers(self):
from google.cloud._http import CLIENT_INFO_HEADER
@@ -319,7 +391,7 @@
"User-Agent": conn.user_agent,
CLIENT_INFO_HEADER: conn.user_agent,
}
- expected_url = "{base}/mock/{version}{path}".format(
+ expected_url = "{base}/mock/{version}{path}?prettyPrint=false".format(
base=conn.API_BASE_URL, version=conn.API_VERSION, path=path
)
http.request.assert_called_once_with(
@@ -481,7 +553,7 @@
"User-Agent": conn.user_agent,
CLIENT_INFO_HEADER: conn.user_agent,
}
- expected_url = "{base}/mock/{version}{path}".format(
+ expected_url = "{base}/mock/{version}{path}?prettyPrint=false".format(
base=conn.API_BASE_URL, version=conn.API_VERSION, path=path
)
http.request.assert_called_once_with(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-cloud-core-1.3.0/tests/unit/test_client.py
new/google-cloud-core-1.6.0/tests/unit/test_client.py
--- old/google-cloud-core-1.3.0/tests/unit/test_client.py 2020-01-31
22:59:39.000000000 +0100
+++ new/google-cloud-core-1.6.0/tests/unit/test_client.py 2021-02-06
02:19:50.000000000 +0100
@@ -22,7 +22,7 @@
def _make_credentials():
import google.auth.credentials
- return mock.Mock(spec=google.auth.credentials.Credentials)
+ return mock.Mock(spec=google.auth.credentials.CredentialsWithQuotaProject)
class Test_ClientFactoryMixin(unittest.TestCase):
@@ -50,14 +50,14 @@
def test_unpickleable(self):
import pickle
- CREDENTIALS = _make_credentials()
+ credentials = _make_credentials()
HTTP = object()
- client_obj = self._make_one(credentials=CREDENTIALS, _http=HTTP)
+ client_obj = self._make_one(credentials=credentials, _http=HTTP)
with self.assertRaises(pickle.PicklingError):
pickle.dumps(client_obj)
- def test_constructor_defaults(self):
+ def test_ctor_defaults(self):
credentials = _make_credentials()
patch = mock.patch("google.auth.default", return_value=(credentials,
None))
@@ -66,9 +66,9 @@
self.assertIs(client_obj._credentials, credentials)
self.assertIsNone(client_obj._http_internal)
- default.assert_called_once_with()
+ default.assert_called_once_with(scopes=None)
- def test_constructor_explicit(self):
+ def test_ctor_explicit(self):
credentials = _make_credentials()
http = mock.sentinel.http
client_obj = self._make_one(credentials=credentials, _http=http)
@@ -76,12 +76,73 @@
self.assertIs(client_obj._credentials, credentials)
self.assertIs(client_obj._http_internal, http)
- def test_constructor_bad_credentials(self):
+ def test_ctor_client_options_w_conflicting_creds(self):
+ from google.api_core.exceptions import DuplicateCredentialArgs
+
+ credentials = _make_credentials()
+ client_options = {'credentials_file': '/path/to/creds.json'}
+ with self.assertRaises(DuplicateCredentialArgs):
+ self._make_one(credentials=credentials,
client_options=client_options)
+
+ def test_ctor_bad_credentials(self):
credentials = mock.sentinel.credentials
with self.assertRaises(ValueError):
self._make_one(credentials=credentials)
+ def test_ctor_client_options_w_creds_file_scopes(self):
+ credentials = _make_credentials()
+ credentials_file = '/path/to/creds.json'
+ scopes = ['SCOPE1', 'SCOPE2']
+ client_options = {'credentials_file': credentials_file, 'scopes':
scopes}
+
+ patch = mock.patch("google.auth.load_credentials_from_file",
return_value=(credentials, None))
+ with patch as load_credentials_from_file:
+ client_obj = self._make_one(client_options=client_options)
+
+ self.assertIs(client_obj._credentials, credentials)
+ self.assertIsNone(client_obj._http_internal)
+ load_credentials_from_file.assert_called_once_with(credentials_file,
scopes=scopes)
+
+ def test_ctor_client_options_w_quota_project(self):
+ credentials = _make_credentials()
+ quota_project_id = 'quota-project-123'
+ client_options = {'quota_project_id': quota_project_id}
+
+ client_obj = self._make_one(credentials=credentials,
client_options=client_options)
+
+ self.assertIs(client_obj._credentials,
credentials.with_quota_project.return_value)
+
credentials.with_quota_project.assert_called_once_with(quota_project_id)
+
+ def test_ctor__http_property_existing(self):
+ credentials = _make_credentials()
+ http = object()
+ client = self._make_one(credentials=credentials, _http=http)
+ self.assertIs(client._http_internal, http)
+ self.assertIs(client._http, http)
+
+ def test_ctor__http_property_new(self):
+ from google.cloud.client import _CREDENTIALS_REFRESH_TIMEOUT
+
+ credentials = _make_credentials()
+ mock_client_cert_source = mock.Mock()
+ client_options = {'client_cert_source': mock_client_cert_source}
+ client = self._make_one(credentials=credentials,
client_options=client_options)
+ self.assertIsNone(client._http_internal)
+
+ with mock.patch('google.auth.transport.requests.AuthorizedSession') as
AuthorizedSession:
+ session = mock.Mock()
+ session.configure_mtls_channel = mock.Mock()
+ AuthorizedSession.return_value = session
+ self.assertIs(client._http, session)
+ # Check the mock.
+ AuthorizedSession.assert_called_once_with(credentials,
refresh_timeout=_CREDENTIALS_REFRESH_TIMEOUT)
+
session.configure_mtls_channel.assert_called_once_with(mock_client_cert_source)
+ # Make sure the cached value is used on subsequent access.
+ self.assertIs(client._http_internal, session)
+ self.assertIs(client._http, session)
+ self.assertEqual(AuthorizedSession.call_count, 1)
+
def test_from_service_account_json(self):
from google.cloud import _helpers
@@ -114,31 +175,131 @@
mock.sentinel.filename, credentials=mock.sentinel.credentials
)
- def test__http_property_existing(self):
- credentials = _make_credentials()
- http = object()
- client = self._make_one(credentials=credentials, _http=http)
- self.assertIs(client._http_internal, http)
- self.assertIs(client._http, http)
- def test__http_property_new(self):
- from google.cloud.client import _CREDENTIALS_REFRESH_TIMEOUT
- credentials = _make_credentials()
- client = self._make_one(credentials=credentials)
- self.assertIsNone(client._http_internal)
+class Test_ClientProjectMixin(unittest.TestCase):
+ @staticmethod
+ def _get_target_class():
+ from google.cloud.client import _ClientProjectMixin
+
+ return _ClientProjectMixin
- authorized_session_patch = mock.patch(
- "google.auth.transport.requests.AuthorizedSession",
- return_value=mock.sentinel.http,
+ def _make_one(self, *args, **kw):
+ return self._get_target_class()(*args, **kw)
+
+ def test_ctor_defaults_wo_envvar(self):
+ environ = {}
+ patch_env = mock.patch("os.environ", new=environ)
+ patch_default = mock.patch(
+ "google.cloud.client._determine_default_project",
+ return_value=None,
)
- with authorized_session_patch as AuthorizedSession:
- self.assertIs(client._http, mock.sentinel.http)
- # Check the mock.
- AuthorizedSession.assert_called_once_with(credentials,
refresh_timeout=_CREDENTIALS_REFRESH_TIMEOUT)
- # Make sure the cached value is used on subsequent access.
- self.assertIs(client._http_internal, mock.sentinel.http)
- self.assertIs(client._http, mock.sentinel.http)
- self.assertEqual(AuthorizedSession.call_count, 1)
+ with patch_env:
+ with patch_default as patched:
+ with self.assertRaises(EnvironmentError):
+ self._make_one()
+
+ patched.assert_called_once_with(None)
+
+ def test_ctor_defaults_w_envvar(self):
+ from google.auth.environment_vars import PROJECT
+
+ project = "some-project-123"
+ environ = {PROJECT: project}
+ patch_env = mock.patch("os.environ", new=environ)
+ with patch_env:
+ client = self._make_one()
+
+ self.assertEqual(client.project, project)
+
+ def test_ctor_defaults_w_legacy_envvar(self):
+ from google.auth.environment_vars import LEGACY_PROJECT
+
+ project = "some-project-123"
+ environ = {LEGACY_PROJECT: project}
+ patch_env = mock.patch("os.environ", new=environ)
+ with patch_env:
+ client = self._make_one()
+
+ self.assertEqual(client.project, project)
+
+ def test_ctor_w_explicit_project(self):
+ explicit_project = "explicit-project-456"
+ patch_default = mock.patch(
+ "google.cloud.client._determine_default_project",
+ return_value=None,
+ )
+ with patch_default as patched:
+ client = self._make_one(project=explicit_project)
+
+ self.assertEqual(client.project, explicit_project)
+
+ patched.assert_not_called()
+
+ def test_ctor_w_explicit_project_bytes(self):
+ explicit_project = b"explicit-project-456"
+ patch_default = mock.patch(
+ "google.cloud.client._determine_default_project",
+ return_value=None,
+ )
+ with patch_default as patched:
+ client = self._make_one(project=explicit_project)
+
+ self.assertEqual(client.project, explicit_project.decode("utf-8"))
+
+ patched.assert_not_called()
+
+ def test_ctor_w_explicit_project_invalid(self):
+ explicit_project = object()
+ patch_default = mock.patch(
+ "google.cloud.client._determine_default_project",
+ return_value=None,
+ )
+ with patch_default as patched:
+ with self.assertRaises(ValueError):
+ self._make_one(project=explicit_project)
+
+ patched.assert_not_called()
+
+ @staticmethod
+ def _make_credentials(**kw):
+ from google.auth.credentials import Credentials
+
+ class _Credentials(Credentials):
+ def __init__(self, **kw):
+ self.__dict__.update(kw)
+
+ def refresh(self): # pragma: NO COVER
+ pass
+
+ return _Credentials(**kw)
+
+ def test_ctor_w_explicit_credentials_wo_project(self):
+ default_project = "default-project-123"
+ credentials = self._make_credentials()
+ patch_default = mock.patch(
+ "google.cloud.client._determine_default_project",
+ return_value=default_project,
+ )
+ with patch_default as patched:
+ client = self._make_one(credentials=credentials)
+
+ self.assertEqual(client.project, default_project)
+
+ patched.assert_called_once_with(None)
+
+ def test_ctor_w_explicit_credentials_w_project(self):
+ project = "credentials-project-456"
+ credentials = self._make_credentials(project_id=project)
+ patch_default = mock.patch(
+ "google.cloud.client._determine_default_project",
+ return_value=None,
+ )
+ with patch_default as patched:
+ client = self._make_one(credentials=credentials)
+
+ self.assertEqual(client.project, project)
+
+ patched.assert_not_called()
class TestClientWithProject(unittest.TestCase):
@@ -167,7 +328,7 @@
self.assertEqual(client_obj.project, project)
self.assertIs(client_obj._credentials, credentials)
self.assertIsNone(client_obj._http_internal)
- default.assert_called_once_with()
+ default.assert_called_once_with(scopes=None)
_determine_default_project.assert_called_once_with(None)
def test_constructor_missing_project(self):