From be1d0856bb9083d3efbf1f5e632950ed7628a1de Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 5 Mar 2021 03:43:27 +0100 Subject: [PATCH 01/13] chore(deps): update dependency google-cloud-error-reporting to v1.1.1 (#86) --- samples/snippets/api/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/api/requirements.txt b/samples/snippets/api/requirements.txt index 1d08c2fb..47f476da 100644 --- a/samples/snippets/api/requirements.txt +++ b/samples/snippets/api/requirements.txt @@ -1 +1 @@ -google-cloud-error-reporting==1.1.0 +google-cloud-error-reporting==1.1.1 From c4b168d1f4e045d72487abba88e118a15b1c99ef Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 5 Mar 2021 16:52:03 +0100 Subject: [PATCH 02/13] chore(deps): update dependency google-cloud-logging to >=1.14.0, <2.3 (#84) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-logging](https://togithub.com/googleapis/python-logging) | `>=1.14.0, <2.2` -> `>=1.14.0, <2.3` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-logging/2.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-logging/2.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-logging/2.2.0/compatibility-slim/2.1.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-logging/2.2.0/confidence-slim/2.1.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-logging ### [`v2.2.0`](https://togithub.com/googleapis/python-logging/blob/master/CHANGELOG.md#​220-httpswwwgithubcomgoogleapispython-loggingcomparev211v220-2021-01-27) [Compare Source](https://togithub.com/googleapis/python-logging/compare/v2.1.1...v2.2.0) ##### Features - add 'from_service_account_info' factory to clients ([a9ff2b7](https://www.github.com/googleapis/python-logging/commit/a9ff2b7984a54542963fc8d52864365ef1562f57)) ##### Bug Fixes - django content length extraction bug ([#​160](https://www.github.com/googleapis/python-logging/issues/160)) ([93eeaef](https://www.github.com/googleapis/python-logging/commit/93eeaef1cce286aa8aa830d2369212b912d184b6)) - fix sphinx identifiers ([a9ff2b7](https://www.github.com/googleapis/python-logging/commit/a9ff2b7984a54542963fc8d52864365ef1562f57)) ##### [2.1.1](https://www.github.com/googleapis/python-logging/compare/v2.1.0...v2.1.1) (2021-01-14) ##### Bug Fixes - use dict for http request ([#​156](https://www.github.com/googleapis/python-logging/issues/156)) ([dc26668](https://www.github.com/googleapis/python-logging/commit/dc266688b1e465112de0e3fe2e8d98003f6e7033))
--- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-error-reporting). --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1a3a2792..623d1235 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ # 'Development Status :: 5 - Production/Stable' release_status = "Development Status :: 4 - Beta" dependencies = [ - "google-cloud-logging>=1.14.0, <2.2", + "google-cloud-logging>=1.14.0, <2.3", "google-api-core[grpc] >= 1.22.0, < 2.0.0dev", "proto-plus >= 1.4.0", "libcst >= 0.2.5", From 108adfd2b1b762472f28b6079a7e5165156e4765 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 11 Mar 2021 22:35:27 +0100 Subject: [PATCH 03/13] chore(deps): update dependency fluent-logger to v0.10.0 (#88) --- samples/snippets/fluent_on_compute/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/fluent_on_compute/requirements.txt b/samples/snippets/fluent_on_compute/requirements.txt index d1c2863f..693841f6 100644 --- a/samples/snippets/fluent_on_compute/requirements.txt +++ b/samples/snippets/fluent_on_compute/requirements.txt @@ -1 +1 @@ -fluent-logger==0.9.6 +fluent-logger==0.10.0 From eaf4a5aebe9f3cee0af211defec7ff10d5bae4a4 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 11 Mar 2021 15:57:24 -0800 Subject: [PATCH 04/13] chore: Re-generated to pick up changes from synthtool. (#77) * changes without context autosynth cannot find the source of changes triggered by earlier changes in this repository, or by version upgrades to tools such as linters. * docs: update python contributing guide Adds details about blacken, updates version for system tests, and shows how to pass through pytest arguments. Source-Author: Chris Cotter Source-Date: Mon Feb 8 17:13:36 2021 -0500 Source-Repo: googleapis/synthtool Source-Sha: 4679e7e415221f03ff2a71e3ffad75b9ec41d87e Source-Link: https://github.com/googleapis/synthtool/commit/4679e7e415221f03ff2a71e3ffad75b9ec41d87e --- CONTRIBUTING.rst | 22 +++++++++++++++---- .../cloud/errorreporting_v1beta1/__init__.py | 4 ++-- synth.metadata | 6 ++--- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c7763dad..e3dee436 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -70,9 +70,14 @@ We use `nox `__ to instrument our tests. - To test your changes, run unit tests with ``nox``:: $ nox -s unit-2.7 - $ nox -s unit-3.7 + $ nox -s unit-3.8 $ ... +- Args to pytest can be passed through the nox command separated by a `--`. For + example, to run a single test:: + + $ nox -s unit-3.8 -- -k + .. note:: The unit tests and system tests are described in the @@ -93,8 +98,12 @@ On Debian/Ubuntu:: ************ Coding Style ************ +- We use the automatic code formatter ``black``. You can run it using + the nox session ``blacken``. This will eliminate many lint errors. Run via:: + + $ nox -s blacken -- PEP8 compliance, with exceptions defined in the linter configuration. +- PEP8 compliance is required, with exceptions defined in the linter configuration. If you have ``nox`` installed, you can test that you have not introduced any non-compliant code via:: @@ -133,13 +142,18 @@ Running System Tests - To run system tests, you can execute:: - $ nox -s system-3.7 + # Run all system tests + $ nox -s system-3.8 $ nox -s system-2.7 + # Run a single system test + $ nox -s system-3.8 -- -k + + .. note:: System tests are only configured to run under Python 2.7 and - Python 3.7. For expediency, we do not run them in older versions + Python 3.8. For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local diff --git a/google/cloud/errorreporting_v1beta1/__init__.py b/google/cloud/errorreporting_v1beta1/__init__.py index 8db40bd7..b6f762a3 100644 --- a/google/cloud/errorreporting_v1beta1/__init__.py +++ b/google/cloud/errorreporting_v1beta1/__init__.py @@ -51,8 +51,8 @@ "ErrorEvent", "ErrorGroup", "ErrorGroupOrder", + "ErrorGroupServiceClient", "ErrorGroupStats", - "ErrorStatsServiceClient", "GetGroupRequest", "HttpRequestContext", "ListEventsRequest", @@ -71,5 +71,5 @@ "TimedCountAlignment", "TrackingIssue", "UpdateGroupRequest", - "ErrorGroupServiceClient", + "ErrorStatsServiceClient", ) diff --git a/synth.metadata b/synth.metadata index 330ea88c..2c79049a 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-error-reporting.git", - "sha": "b6887650c28d9fce253ed5894bb2d64a4fedae19" + "sha": "e078a158b68d10b119ec226c02a17944b59ddccb" } }, { @@ -19,14 +19,14 @@ "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "33366574ffb9e11737b3547eb6f020ecae0536e8" + "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "33366574ffb9e11737b3547eb6f020ecae0536e8" + "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" } } ], From c67ea454d69751e9e3508a152d17798e969c13a7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 25 Mar 2021 00:38:04 +0100 Subject: [PATCH 05/13] chore(deps): update precommit hook pycqa/flake8 to v3.9.0 (#90) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a9024b15..32302e48 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,6 +12,6 @@ repos: hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 + rev: 3.9.0 hooks: - id: flake8 From cc17681b2a8f1bd00dca9d101a5e64dc5caac51c Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 24 Mar 2021 16:38:36 -0700 Subject: [PATCH 06/13] chore: Re-generated to pick up changes from synthtool. (#89) --- .gitignore | 4 +++- .kokoro/build.sh | 10 ++++++++++ .../cloud/errorreporting_v1beta1/__init__.py | 4 ++-- noxfile.py | 20 +++++++++++++++++-- synth.metadata | 6 +++--- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index b9daa52f..b4243ced 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,10 @@ docs.metadata # Virtual environment env/ + +# Test logs coverage.xml -sponge_log.xml +*sponge_log.xml # System test environment variables. system_tests/local_test_setup diff --git a/.kokoro/build.sh b/.kokoro/build.sh index 2a8a5044..4f96711f 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -40,6 +40,16 @@ python3 -m pip uninstall --yes --quiet nox-automation python3 -m pip install --upgrade --quiet nox python3 -m nox --version +# If this is a continuous build, send the test log to the FlakyBot. +# See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. +if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then + cleanup() { + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + } + trap cleanup EXIT HUP +fi + # If NOX_SESSION is set, it only runs the specified session, # otherwise run all the sessions. if [[ -n "${NOX_SESSION:-}" ]]; then diff --git a/google/cloud/errorreporting_v1beta1/__init__.py b/google/cloud/errorreporting_v1beta1/__init__.py index b6f762a3..8db40bd7 100644 --- a/google/cloud/errorreporting_v1beta1/__init__.py +++ b/google/cloud/errorreporting_v1beta1/__init__.py @@ -51,8 +51,8 @@ "ErrorEvent", "ErrorGroup", "ErrorGroupOrder", - "ErrorGroupServiceClient", "ErrorGroupStats", + "ErrorStatsServiceClient", "GetGroupRequest", "HttpRequestContext", "ListEventsRequest", @@ -71,5 +71,5 @@ "TimedCountAlignment", "TrackingIssue", "UpdateGroupRequest", - "ErrorStatsServiceClient", + "ErrorGroupServiceClient", ) diff --git a/noxfile.py b/noxfile.py index 544b90d7..4e86e3af 100644 --- a/noxfile.py +++ b/noxfile.py @@ -93,6 +93,7 @@ def default(session): session.run( "py.test", "--quiet", + f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google/cloud", "--cov=tests/unit", "--cov-append", @@ -122,6 +123,9 @@ def system(session): # Sanity check: Only run tests if the environment variable is set. if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): session.skip("Credentials must be set via environment variable") + # Install pyopenssl for mTLS testing. + if os.environ.get("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true": + session.install("pyopenssl") system_test_exists = os.path.exists(system_test_path) system_test_folder_exists = os.path.exists(system_test_folder_path) @@ -143,9 +147,21 @@ def system(session): # Run py.test against the system tests. if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_path, + *session.posargs, + ) if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_folder_path, + *session.posargs, + ) @nox.session(python=DEFAULT_PYTHON_VERSION) diff --git a/synth.metadata b/synth.metadata index 2c79049a..f49b243b 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-error-reporting.git", - "sha": "e078a158b68d10b119ec226c02a17944b59ddccb" + "sha": "eaf4a5aebe9f3cee0af211defec7ff10d5bae4a4" } }, { @@ -19,14 +19,14 @@ "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" + "sha": "0780323da96d5a53925fe0547757181fe76e8f1e" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" + "sha": "0780323da96d5a53925fe0547757181fe76e8f1e" } } ], From ed52ba68b5771b996c704c130393ddba35ba045a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 31 Mar 2021 23:25:19 +0200 Subject: [PATCH 07/13] chore(deps): update dependency google-cloud-logging to >=1.14.0, <2.4 (#95) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 623d1235..d40cc0d7 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ # 'Development Status :: 5 - Production/Stable' release_status = "Development Status :: 4 - Beta" dependencies = [ - "google-cloud-logging>=1.14.0, <2.3", + "google-cloud-logging>=1.14.0, <2.4", "google-api-core[grpc] >= 1.22.0, < 2.0.0dev", "proto-plus >= 1.4.0", "libcst >= 0.2.5", From 3f3e5add4050369ba2de51025bfedee76b82bfdd Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 31 Mar 2021 14:27:50 -0700 Subject: [PATCH 08/13] chore: Re-generated to pick up changes from googleapis. (#87) * fix: remove client recv msg limit fix: add enums to `types/__init__.py` PiperOrigin-RevId: 347055288 Source-Author: Google APIs Source-Date: Fri Dec 11 12:44:37 2020 -0800 Source-Repo: googleapis/googleapis Source-Sha: dd372aa22ded7a8ba6f0e03a80e06358a3fa0907 Source-Link: https://github.com/googleapis/googleapis/commit/dd372aa22ded7a8ba6f0e03a80e06358a3fa0907 * docs: put FPS table in code block PiperOrigin-RevId: 348857882 Source-Author: Google APIs Source-Date: Wed Dec 23 15:47:05 2020 -0800 Source-Repo: googleapis/googleapis Source-Sha: 2ccf8f460800e98884d1aa4ba61e344ad4cd5d04 Source-Link: https://github.com/googleapis/googleapis/commit/2ccf8f460800e98884d1aa4ba61e344ad4cd5d04 * chore: upgrade gapic-generator-python to 0.39.1 feat: add 'from_service_account_info' factory to clients fix: fix sphinx identifiers PiperOrigin-RevId: 350246057 Source-Author: Google APIs Source-Date: Tue Jan 5 16:44:11 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 520682435235d9c503983a360a2090025aa47cd1 Source-Link: https://github.com/googleapis/googleapis/commit/520682435235d9c503983a360a2090025aa47cd1 * chore: Update C# namespace This is a breaking change, but *only* for C#. Google has not yet published a package for this API, so it would only break users who have generated the code themselves. PiperOrigin-RevId: 350388717 Source-Author: Google APIs Source-Date: Wed Jan 6 11:04:54 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: dd1d2325b189d3bb69c4a6a802185cefbd8e592e Source-Link: https://github.com/googleapis/googleapis/commit/dd1d2325b189d3bb69c4a6a802185cefbd8e592e * chore: put markdown table in a codeblock PiperOrigin-RevId: 350414815 Source-Author: Google APIs Source-Date: Wed Jan 6 13:18:46 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 700afd1f0bafc2155bc5e891504c53d4ac9166f5 Source-Link: https://github.com/googleapis/googleapis/commit/700afd1f0bafc2155bc5e891504c53d4ac9166f5 * chore: use name google.cloud.bigquery_storage namespace to avoid conflicts with google.cloud.bigquery PiperOrigin-RevId: 351218127 Source-Author: Google APIs Source-Date: Mon Jan 11 13:04:39 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: c8bfd324b41ad1f6f65fed124572f92fe116517b Source-Link: https://github.com/googleapis/googleapis/commit/c8bfd324b41ad1f6f65fed124572f92fe116517b * feat: add C++ targets for DialogFlow PiperOrigin-RevId: 351615861 Source-Author: Google APIs Source-Date: Wed Jan 13 10:31:46 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: a515fa4183cb95089af55020ab547081714c5a7b Source-Link: https://github.com/googleapis/googleapis/commit/a515fa4183cb95089af55020ab547081714c5a7b * feat: added client library for Workflows Executions V1 API PiperOrigin-RevId: 351618705 Source-Author: Google APIs Source-Date: Wed Jan 13 10:45:45 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 98911d3e77f3d541eaa841252a44905ea4a430ab Source-Link: https://github.com/googleapis/googleapis/commit/98911d3e77f3d541eaa841252a44905ea4a430ab * chore: migrate texttospeech v1beta1 to python microgenerator PiperOrigin-RevId: 352645446 Source-Author: Google APIs Source-Date: Tue Jan 19 13:45:56 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 4d19fc01775b142dd392f4bd82bdf8810202d061 Source-Link: https://github.com/googleapis/googleapis/commit/4d19fc01775b142dd392f4bd82bdf8810202d061 * chore: update Go generator, rules_go, and protobuf PiperOrigin-RevId: 352816749 Source-Author: Google APIs Source-Date: Wed Jan 20 10:06:23 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: ceaaf31b3d13badab7cf9d3b570f5639db5593d9 Source-Link: https://github.com/googleapis/googleapis/commit/ceaaf31b3d13badab7cf9d3b570f5639db5593d9 * chore: upgrade gapic-generator-python to 0.40.5 PiperOrigin-RevId: 354996675 Source-Author: Google APIs Source-Date: Mon Feb 1 12:11:49 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 20712b8fe95001b312f62c6c5f33e3e3ec92cfaf Source-Link: https://github.com/googleapis/googleapis/commit/20712b8fe95001b312f62c6c5f33e3e3ec92cfaf * feat: Add Pub/Sub endpoints for Cloud Channel API. PiperOrigin-RevId: 355059873 Source-Author: Google APIs Source-Date: Mon Feb 1 17:13:22 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 6ef9eaea379fc1cc0355e06a5a20b594543ee693 Source-Link: https://github.com/googleapis/googleapis/commit/6ef9eaea379fc1cc0355e06a5a20b594543ee693 * fix: add proto opts & bazel targets to metadata PiperOrigin-RevId: 355748843 Source-Author: Google APIs Source-Date: Thu Feb 4 17:39:02 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: dccd3ea36ba19b88b978c521f5088eddd087c414 Source-Link: https://github.com/googleapis/googleapis/commit/dccd3ea36ba19b88b978c521f5088eddd087c414 * build: change package name to correct name PiperOrigin-RevId: 355768365 Source-Author: Google APIs Source-Date: Thu Feb 4 20:11:22 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: bb17e41ec1e9f1197520560bc13cc5da24e04e6f Source-Link: https://github.com/googleapis/googleapis/commit/bb17e41ec1e9f1197520560bc13cc5da24e04e6f * fix: Update bazel builds for ER client libraries. PiperOrigin-RevId: 355832930 Source-Author: Google APIs Source-Date: Fri Feb 5 05:42:21 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 408590478542a058f2f1a706a402beb44844f66b Source-Link: https://github.com/googleapis/googleapis/commit/408590478542a058f2f1a706a402beb44844f66b * fix: Fix constraint resource pattern annotation PiperOrigin-RevId: 355915985 Source-Author: Google APIs Source-Date: Fri Feb 5 13:27:16 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 35ce99fec72979f6f9b2a5adae835a49648a3231 Source-Link: https://github.com/googleapis/googleapis/commit/35ce99fec72979f6f9b2a5adae835a49648a3231 * chore: update gapic-generator-python PiperOrigin-RevId: 355923884 Source-Author: Google APIs Source-Date: Fri Feb 5 14:04:52 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 5e3dacee19405529b841b53797df799c2383536c Source-Link: https://github.com/googleapis/googleapis/commit/5e3dacee19405529b841b53797df799c2383536c * chore(python): include py.typed files in release A py.typed file must be included in the released package for it to be considered typed by type checkers. https://www.python.org/dev/peps/pep-0561/#packaging-type-information. See https://github.com/googleapis/python-secret-manager/issues/79 Source-Author: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Source-Date: Fri Feb 5 17:32:06 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: 33366574ffb9e11737b3547eb6f020ecae0536e8 Source-Link: https://github.com/googleapis/synthtool/commit/33366574ffb9e11737b3547eb6f020ecae0536e8 * feat: Make resolution status field available for error groups. Now callers can set the status of an error group by passing this to UpdateGroup. When not specified, it's treated like OPEN. feat: Make source location available for error groups created from GAE. PiperOrigin-RevId: 356330876 Source-Author: Google APIs Source-Date: Mon Feb 8 12:48:44 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: c1e59709c1d28795fe9b70eb479579556056bfad Source-Link: https://github.com/googleapis/googleapis/commit/c1e59709c1d28795fe9b70eb479579556056bfad * fix: Remove dependency on AppEngine's proto definitions. This also removes the source_references field. PiperOrigin-RevId: 356540804 Source-Author: Google APIs Source-Date: Tue Feb 9 10:53:59 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 4f60776fe99f1fd8261b6a0493a5f5f4d7e8d969 Source-Link: https://github.com/googleapis/googleapis/commit/4f60776fe99f1fd8261b6a0493a5f5f4d7e8d969 * docs: Update rules for currency_code in budget_amount. PiperOrigin-RevId: 357051517 Source-Author: Google APIs Source-Date: Thu Feb 11 13:54:03 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: f3a60f63c13fb434745ea59b990a82d6ffc803b5 Source-Link: https://github.com/googleapis/googleapis/commit/f3a60f63c13fb434745ea59b990a82d6ffc803b5 * feat: Update documentai/v1beta3 protos: add support for boolean normalized value PiperOrigin-RevId: 359109762 Source-Author: Google APIs Source-Date: Tue Feb 23 12:45:26 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 8c058c505afc717966bc815075bdd11ff76618e5 Source-Link: https://github.com/googleapis/googleapis/commit/8c058c505afc717966bc815075bdd11ff76618e5 * chore: update gapic-generator-python to 0.40.11 PiperOrigin-RevId: 359562873 Source-Author: Google APIs Source-Date: Thu Feb 25 10:52:32 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: 07932bb995e7dc91b43620ea8402c6668c7d102c Source-Link: https://github.com/googleapis/googleapis/commit/07932bb995e7dc91b43620ea8402c6668c7d102c * chore: clean up unused gapic.legacy.yaml files Committer: @miraleung PiperOrigin-RevId: 359580699 Source-Author: Google APIs Source-Date: Thu Feb 25 12:03:52 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: d9b32e92fa57c37e5af0dc03badfe741170c5849 Source-Link: https://github.com/googleapis/googleapis/commit/d9b32e92fa57c37e5af0dc03badfe741170c5849 * chore: update protobuf v3.15.3 This release makes --experimental_allow_proto3_optional no longer necessary. PiperOrigin-RevId: 359781040 Source-Author: Google APIs Source-Date: Fri Feb 26 09:59:49 2021 -0800 Source-Repo: googleapis/googleapis Source-Sha: f6dd7e47620566925a4b3f1ce029e74e1b2f2516 Source-Link: https://github.com/googleapis/googleapis/commit/f6dd7e47620566925a4b3f1ce029e74e1b2f2516 Co-authored-by: Daniel Sanche --- .coveragerc | 22 +- .../error_group_service.rst | 6 + .../error_stats_service.rst | 11 + .../report_errors_service.rst | 6 + docs/errorreporting_v1beta1/services.rst | 14 +- docs/errorreporting_v1beta1/types.rst | 1 + .../cloud/errorreporting_v1beta1/__init__.py | 6 +- .../errorreporting_v1beta1/proto/common.proto | 31 +- .../proto/error_group_service.proto | 5 +- .../proto/error_stats_service.proto | 17 +- .../proto/report_errors_service.proto | 22 +- .../error_group_service/async_client.py | 45 ++- .../services/error_group_service/client.py | 56 ++-- .../error_group_service/transports/grpc.py | 23 +- .../transports/grpc_asyncio.py | 23 +- .../error_stats_service/async_client.py | 76 +++-- .../services/error_stats_service/client.py | 93 +++--- .../services/error_stats_service/pagers.py | 43 +-- .../error_stats_service/transports/grpc.py | 23 +- .../transports/grpc_asyncio.py | 23 +- .../report_errors_service/async_client.py | 58 +++- .../services/report_errors_service/client.py | 69 +++-- .../report_errors_service/transports/grpc.py | 35 ++- .../transports/grpc_asyncio.py | 35 ++- .../errorreporting_v1beta1/types/__init__.py | 2 + .../errorreporting_v1beta1/types/common.py | 30 +- .../types/error_group_service.py | 4 +- .../types/error_stats_service.py | 64 ++-- .../types/report_errors_service.py | 15 +- synth.metadata | 10 +- .../gapic/errorreporting_v1beta1/__init__.py | 15 + .../test_error_group_service.py | 278 ++++++++++++------ .../test_error_stats_service.py | 266 ++++++++++++----- .../test_report_errors_service.py | 236 ++++++++++----- 34 files changed, 1141 insertions(+), 522 deletions(-) create mode 100644 docs/errorreporting_v1beta1/error_group_service.rst create mode 100644 docs/errorreporting_v1beta1/error_stats_service.rst create mode 100644 docs/errorreporting_v1beta1/report_errors_service.rst diff --git a/.coveragerc b/.coveragerc index 10cb72e8..9a9b9f3e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,27 +1,11 @@ -# -*- 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! [run] branch = True [report] fail_under = 100 show_missing = True -omit = google/cloud/errorreporting/__init__.py, .nox/* +omit = + google/cloud/errorreporting/__init__.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER @@ -31,4 +15,4 @@ exclude_lines = # This is added at the module level as a safeguard for if someone # generates the code and tries to run it without pip installing. This # makes it virtually impossible to test properly. - except pkg_resources.DistributionNotFound \ No newline at end of file + except pkg_resources.DistributionNotFound diff --git a/docs/errorreporting_v1beta1/error_group_service.rst b/docs/errorreporting_v1beta1/error_group_service.rst new file mode 100644 index 00000000..dd213525 --- /dev/null +++ b/docs/errorreporting_v1beta1/error_group_service.rst @@ -0,0 +1,6 @@ +ErrorGroupService +----------------------------------- + +.. automodule:: google.cloud.errorreporting_v1beta1.services.error_group_service + :members: + :inherited-members: diff --git a/docs/errorreporting_v1beta1/error_stats_service.rst b/docs/errorreporting_v1beta1/error_stats_service.rst new file mode 100644 index 00000000..30d29e69 --- /dev/null +++ b/docs/errorreporting_v1beta1/error_stats_service.rst @@ -0,0 +1,11 @@ +ErrorStatsService +----------------------------------- + +.. automodule:: google.cloud.errorreporting_v1beta1.services.error_stats_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.errorreporting_v1beta1.services.error_stats_service.pagers + :members: + :inherited-members: diff --git a/docs/errorreporting_v1beta1/report_errors_service.rst b/docs/errorreporting_v1beta1/report_errors_service.rst new file mode 100644 index 00000000..ccddb8b0 --- /dev/null +++ b/docs/errorreporting_v1beta1/report_errors_service.rst @@ -0,0 +1,6 @@ +ReportErrorsService +------------------------------------- + +.. automodule:: google.cloud.errorreporting_v1beta1.services.report_errors_service + :members: + :inherited-members: diff --git a/docs/errorreporting_v1beta1/services.rst b/docs/errorreporting_v1beta1/services.rst index a5ec3b92..e888027f 100644 --- a/docs/errorreporting_v1beta1/services.rst +++ b/docs/errorreporting_v1beta1/services.rst @@ -1,12 +1,8 @@ Services for Google Cloud Errorreporting v1beta1 API ==================================================== +.. toctree:: + :maxdepth: 2 -.. automodule:: google.cloud.errorreporting_v1beta1.services.error_group_service - :members: - :inherited-members: -.. automodule:: google.cloud.errorreporting_v1beta1.services.error_stats_service - :members: - :inherited-members: -.. automodule:: google.cloud.errorreporting_v1beta1.services.report_errors_service - :members: - :inherited-members: + error_group_service + error_stats_service + report_errors_service diff --git a/docs/errorreporting_v1beta1/types.rst b/docs/errorreporting_v1beta1/types.rst index 08851dbe..179256c7 100644 --- a/docs/errorreporting_v1beta1/types.rst +++ b/docs/errorreporting_v1beta1/types.rst @@ -3,4 +3,5 @@ Types for Google Cloud Errorreporting v1beta1 API .. automodule:: google.cloud.errorreporting_v1beta1.types :members: + :undoc-members: :show-inheritance: diff --git a/google/cloud/errorreporting_v1beta1/__init__.py b/google/cloud/errorreporting_v1beta1/__init__.py index 8db40bd7..8ced2656 100644 --- a/google/cloud/errorreporting_v1beta1/__init__.py +++ b/google/cloud/errorreporting_v1beta1/__init__.py @@ -22,6 +22,7 @@ from .types.common import ErrorEvent from .types.common import ErrorGroup from .types.common import HttpRequestContext +from .types.common import ResolutionStatus from .types.common import ServiceContext from .types.common import SourceLocation from .types.common import TrackingIssue @@ -51,6 +52,7 @@ "ErrorEvent", "ErrorGroup", "ErrorGroupOrder", + "ErrorGroupServiceClient", "ErrorGroupStats", "ErrorStatsServiceClient", "GetGroupRequest", @@ -62,8 +64,8 @@ "QueryTimeRange", "ReportErrorEventRequest", "ReportErrorEventResponse", - "ReportErrorsServiceClient", "ReportedErrorEvent", + "ResolutionStatus", "ServiceContext", "ServiceContextFilter", "SourceLocation", @@ -71,5 +73,5 @@ "TimedCountAlignment", "TrackingIssue", "UpdateGroupRequest", - "ErrorGroupServiceClient", + "ReportErrorsServiceClient", ) diff --git a/google/cloud/errorreporting_v1beta1/proto/common.proto b/google/cloud/errorreporting_v1beta1/proto/common.proto index 7a1d2003..e9bb321e 100644 --- a/google/cloud/errorreporting_v1beta1/proto/common.proto +++ b/google/cloud/errorreporting_v1beta1/proto/common.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,9 +16,9 @@ syntax = "proto3"; package google.devtools.clouderrorreporting.v1beta1; -import "google/api/annotations.proto"; import "google/api/resource.proto"; import "google/protobuf/timestamp.proto"; +import "google/api/annotations.proto"; option cc_enable_arenas = true; option csharp_namespace = "Google.Cloud.ErrorReporting.V1Beta1"; @@ -37,7 +37,7 @@ message ErrorGroup { }; // The group resource name. - // Example: projects/my-project-123/groups/my-groupid + // Example: projects/my-project-123/groups/CNSgkpnppqKCUw string name = 1; // Group IDs are unique for a given project. If the same kind of error @@ -46,6 +46,10 @@ message ErrorGroup { // Associated tracking issues. repeated TrackingIssue tracking_issues = 3; + + // Error group's resolution status. + // An unspecified resolution status will be interpreted as OPEN + ResolutionStatus resolution_status = 5; } // Information related to tracking the progress on resolving the error. @@ -169,3 +173,24 @@ message SourceLocation { // For example, `my.package.MyClass.method` in case of Java. string function_name = 4; } + +// Resolution status of an error group. +enum ResolutionStatus { + // Status is unknown. When left unspecified in requests, it is treated like + // OPEN. + RESOLUTION_STATUS_UNSPECIFIED = 0; + + // The error group is not being addressed. This is the default for + // new groups. It is also used for errors re-occurring after marked RESOLVED. + OPEN = 1; + + // Error Group manually acknowledged, it can have an issue link attached. + ACKNOWLEDGED = 2; + + // Error Group manually resolved, more events for this group are not expected + // to occur. + RESOLVED = 3; + + // The error group is muted and excluded by default on group stats requests. + MUTED = 4; +} diff --git a/google/cloud/errorreporting_v1beta1/proto/error_group_service.proto b/google/cloud/errorreporting_v1beta1/proto/error_group_service.proto index 18182729..0104b62d 100644 --- a/google/cloud/errorreporting_v1beta1/proto/error_group_service.proto +++ b/google/cloud/errorreporting_v1beta1/proto/error_group_service.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; @@ -58,7 +57,7 @@ service ErrorGroupService { // A request to return an individual group. message GetGroupRequest { - // The group resource name. Written as + // Required. The group resource name. Written as // `projects/{projectID}/groups/{group_name}`. Call // [`groupStats.list`](https://cloud.google.com/error-reporting/reference/rest/v1beta1/projects.groupStats/list) // to return a list of groups belonging to this project. diff --git a/google/cloud/errorreporting_v1beta1/proto/error_stats_service.proto b/google/cloud/errorreporting_v1beta1/proto/error_stats_service.proto index 0773f488..6c62edd9 100644 --- a/google/cloud/errorreporting_v1beta1/proto/error_stats_service.proto +++ b/google/cloud/errorreporting_v1beta1/proto/error_stats_service.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; @@ -68,11 +67,11 @@ service ErrorStatsService { // Specifies a set of `ErrorGroupStats` to return. message ListGroupStatsRequest { // Required. The resource name of the Google Cloud Platform project. Written - // as projects/ plus the - // Google Cloud - // Platform project ID. + // as `projects/{projectID}` or `projects/{projectNumber}`, where `{projectID}` + // and `{projectNumber}` can be found in the + // [Google Cloud Console](https://support.google.com/cloud/answer/6158840). // - // Example: projects/my-project-123. + // Examples: `projects/my-project-123`, `projects/5551234`. string project_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { @@ -258,9 +257,10 @@ enum ErrorGroupOrder { // Specifies a set of error events to return. message ListEventsRequest { // Required. The resource name of the Google Cloud Platform project. Written - // as `projects/` plus the + // as `projects/{projectID}`, where `{projectID}` is the // [Google Cloud Platform project // ID](https://support.google.com/cloud/answer/6158840). + // // Example: `projects/my-project-123`. string project_name = 1 [ (google.api.field_behavior) = REQUIRED, @@ -357,9 +357,10 @@ message ServiceContextFilter { // Deletes all events in the project. message DeleteEventsRequest { // Required. The resource name of the Google Cloud Platform project. Written - // as `projects/` plus the + // as `projects/{projectID}`, where `{projectID}` is the // [Google Cloud Platform project // ID](https://support.google.com/cloud/answer/6158840). + // // Example: `projects/my-project-123`. string project_name = 1 [ (google.api.field_behavior) = REQUIRED, diff --git a/google/cloud/errorreporting_v1beta1/proto/report_errors_service.proto b/google/cloud/errorreporting_v1beta1/proto/report_errors_service.proto index f46f546d..cd1e5100 100644 --- a/google/cloud/errorreporting_v1beta1/proto/report_errors_service.proto +++ b/google/cloud/errorreporting_v1beta1/proto/report_errors_service.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; @@ -38,7 +37,7 @@ service ReportErrorsService { option (google.api.default_host) = "clouderrorreporting.googleapis.com"; option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - // Report an individual error event. + // Report an individual error event and record the event to a log. // // This endpoint accepts **either** an OAuth token, // **or** an [API key](https://support.google.com/cloud/answer/6158862) @@ -46,7 +45,15 @@ service ReportErrorsService { // a `key` parameter. For example: // // `POST - // https://clouderrorreporting.googleapis.com/v1beta1/projects/example-project/events:report?key=123ABC456` + // https://clouderrorreporting.googleapis.com/v1beta1/{projectName}/events:report?key=123ABC456` + // + // **Note:** [Error Reporting](/error-reporting) is a global service built + // on Cloud Logging and doesn't analyze logs stored + // in regional log buckets or logs routed to other Google Cloud projects. + // + // For more information, see + // [Using Error Reporting with regionalized + // logs](/error-reporting/docs/regionalization). rpc ReportErrorEvent(ReportErrorEventRequest) returns (ReportErrorEventResponse) { option (google.api.http) = { post: "/v1beta1/{project_name=projects/*}/events:report" @@ -59,10 +66,11 @@ service ReportErrorsService { // A request for reporting an individual error event. message ReportErrorEventRequest { // Required. The resource name of the Google Cloud Platform project. Written - // as `projects/` plus the + // as `projects/{projectId}`, where `{projectId}` is the // [Google Cloud Platform project - // ID](https://support.google.com/cloud/answer/6158840). Example: - // `projects/my-project-123`. + // ID](https://support.google.com/cloud/answer/6158840). + // + // Example: // `projects/my-project-123`. string project_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { diff --git a/google/cloud/errorreporting_v1beta1/services/error_group_service/async_client.py b/google/cloud/errorreporting_v1beta1/services/error_group_service/async_client.py index 26c03996..e2af4bb2 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_group_service/async_client.py +++ b/google/cloud/errorreporting_v1beta1/services/error_group_service/async_client.py @@ -78,7 +78,36 @@ class ErrorGroupServiceAsyncClient: ErrorGroupServiceClient.parse_common_location_path ) - from_service_account_file = ErrorGroupServiceClient.from_service_account_file + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ErrorGroupServiceAsyncClient: The constructed client. + """ + return ErrorGroupServiceClient.from_service_account_info.__func__(ErrorGroupServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ErrorGroupServiceAsyncClient: The constructed client. + """ + return ErrorGroupServiceClient.from_service_account_file.__func__(ErrorGroupServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -154,16 +183,17 @@ async def get_group( r"""Get the specified group. Args: - request (:class:`~.error_group_service.GetGroupRequest`): + request (:class:`google.cloud.errorreporting_v1beta1.types.GetGroupRequest`): The request object. A request to return an individual group. group_name (:class:`str`): - The group resource name. Written as + Required. The group resource name. Written as ``projects/{projectID}/groups/{group_name}``. Call ```groupStats.list`` `__ to return a list of groups belonging to this project. Example: ``projects/my-project-123/groups/my-group`` + This corresponds to the ``group_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -175,7 +205,7 @@ async def get_group( sent along with the request as metadata. Returns: - ~.common.ErrorGroup: + google.cloud.errorreporting_v1beta1.types.ErrorGroup: Description of a group of similar error events. @@ -233,12 +263,13 @@ async def update_group( Fails if the group does not exist. Args: - request (:class:`~.error_group_service.UpdateGroupRequest`): + request (:class:`google.cloud.errorreporting_v1beta1.types.UpdateGroupRequest`): The request object. A request to replace the existing data for the given group. - group (:class:`~.common.ErrorGroup`): + group (:class:`google.cloud.errorreporting_v1beta1.types.ErrorGroup`): Required. The group which replaces the resource on the server. + This corresponds to the ``group`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -250,7 +281,7 @@ async def update_group( sent along with the request as metadata. Returns: - ~.common.ErrorGroup: + google.cloud.errorreporting_v1beta1.types.ErrorGroup: Description of a group of similar error events. diff --git a/google/cloud/errorreporting_v1beta1/services/error_group_service/client.py b/google/cloud/errorreporting_v1beta1/services/error_group_service/client.py index d1656df2..db374a93 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_group_service/client.py +++ b/google/cloud/errorreporting_v1beta1/services/error_group_service/client.py @@ -112,6 +112,22 @@ def _get_default_mtls_endpoint(api_endpoint): DEFAULT_ENDPOINT ) + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ErrorGroupServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -124,7 +140,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): kwargs: Additional arguments to pass to the constructor. Returns: - {@api.name}: The constructed client. + ErrorGroupServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -227,10 +243,10 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.ErrorGroupServiceTransport]): The + transport (Union[str, ErrorGroupServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (client_options_lib.ClientOptions): Custom options for the + client_options (google.api_core.client_options.ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT @@ -266,21 +282,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -323,7 +335,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) @@ -340,16 +352,17 @@ def get_group( r"""Get the specified group. Args: - request (:class:`~.error_group_service.GetGroupRequest`): + request (google.cloud.errorreporting_v1beta1.types.GetGroupRequest): The request object. A request to return an individual group. - group_name (:class:`str`): - The group resource name. Written as + group_name (str): + Required. The group resource name. Written as ``projects/{projectID}/groups/{group_name}``. Call ```groupStats.list`` `__ to return a list of groups belonging to this project. Example: ``projects/my-project-123/groups/my-group`` + This corresponds to the ``group_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -361,7 +374,7 @@ def get_group( sent along with the request as metadata. Returns: - ~.common.ErrorGroup: + google.cloud.errorreporting_v1beta1.types.ErrorGroup: Description of a group of similar error events. @@ -420,12 +433,13 @@ def update_group( Fails if the group does not exist. Args: - request (:class:`~.error_group_service.UpdateGroupRequest`): + request (google.cloud.errorreporting_v1beta1.types.UpdateGroupRequest): The request object. A request to replace the existing data for the given group. - group (:class:`~.common.ErrorGroup`): + group (google.cloud.errorreporting_v1beta1.types.ErrorGroup): Required. The group which replaces the resource on the server. + This corresponds to the ``group`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -437,7 +451,7 @@ def update_group( sent along with the request as metadata. Returns: - ~.common.ErrorGroup: + google.cloud.errorreporting_v1beta1.types.ErrorGroup: Description of a group of similar error events. diff --git a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py index 102cdd39..b6a71e1f 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py +++ b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py @@ -58,6 +58,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -88,6 +89,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -104,6 +109,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -113,11 +123,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -161,12 +166,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py index f6ed3855..6fd73663 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py +++ b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py @@ -102,6 +102,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -133,6 +134,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -149,6 +154,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -158,11 +168,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -206,12 +211,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/async_client.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/async_client.py index 20e91256..ca116141 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/async_client.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/async_client.py @@ -81,7 +81,36 @@ class ErrorStatsServiceAsyncClient: ErrorStatsServiceClient.parse_common_location_path ) - from_service_account_file = ErrorStatsServiceClient.from_service_account_file + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ErrorStatsServiceAsyncClient: The constructed client. + """ + return ErrorStatsServiceClient.from_service_account_info.__func__(ErrorStatsServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ErrorStatsServiceAsyncClient: The constructed client. + """ + return ErrorStatsServiceClient.from_service_account_file.__func__(ErrorStatsServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -158,22 +187,23 @@ async def list_group_stats( r"""Lists the specified groups. Args: - request (:class:`~.error_stats_service.ListGroupStatsRequest`): + request (:class:`google.cloud.errorreporting_v1beta1.types.ListGroupStatsRequest`): The request object. Specifies a set of `ErrorGroupStats` to return. project_name (:class:`str`): - Required. The resource name of the - Google Cloud Platform project. Written - as projects/ plus the Google - Cloud Platform project ID. - - Example: projects/my- - project-123. + Required. The resource name of the Google Cloud Platform + project. Written as ``projects/{projectID}`` or + ``projects/{projectNumber}``, where ``{projectID}`` and + ``{projectNumber}`` can be found in the `Google Cloud + Console `__. + + Examples: ``projects/my-project-123``, + ``projects/5551234``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - time_range (:class:`~.error_stats_service.QueryTimeRange`): + time_range (:class:`google.cloud.errorreporting_v1beta1.types.QueryTimeRange`): Optional. List data for the given time range. If not set, a default time range is used. The field time_range_begin in the response will specify the @@ -182,6 +212,7 @@ async def list_group_stats( unless the request contains an explicit group_id list. If a group_id list is given, also ErrorGroupStats with zero occurrences are returned. + This corresponds to the ``time_range`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -193,7 +224,7 @@ async def list_group_stats( sent along with the request as metadata. Returns: - ~.pagers.ListGroupStatsAsyncPager: + google.cloud.errorreporting_v1beta1.services.error_stats_service.pagers.ListGroupStatsAsyncPager: Contains a set of requested error group stats. Iterating over this object will yield @@ -262,21 +293,24 @@ async def list_events( r"""Lists the specified events. Args: - request (:class:`~.error_stats_service.ListEventsRequest`): + request (:class:`google.cloud.errorreporting_v1beta1.types.ListEventsRequest`): The request object. Specifies a set of error events to return. project_name (:class:`str`): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectID}``, where + ``{projectID}`` is the `Google Cloud Platform project ID `__. + Example: ``projects/my-project-123``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. group_id (:class:`str`): Required. The group for which events shall be returned. + This corresponds to the ``group_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -288,7 +322,7 @@ async def list_events( sent along with the request as metadata. Returns: - ~.pagers.ListEventsAsyncPager: + google.cloud.errorreporting_v1beta1.services.error_stats_service.pagers.ListEventsAsyncPager: Contains a set of requested error events. Iterating over this object will yield @@ -356,14 +390,16 @@ async def delete_events( r"""Deletes all error events of a given project. Args: - request (:class:`~.error_stats_service.DeleteEventsRequest`): + request (:class:`google.cloud.errorreporting_v1beta1.types.DeleteEventsRequest`): The request object. Deletes all events in the project. project_name (:class:`str`): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectID}``, where + ``{projectID}`` is the `Google Cloud Platform project ID `__. + Example: ``projects/my-project-123``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -375,7 +411,7 @@ async def delete_events( sent along with the request as metadata. Returns: - ~.error_stats_service.DeleteEventsResponse: + google.cloud.errorreporting_v1beta1.types.DeleteEventsResponse: Response message for deleting error events. diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/client.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/client.py index f04fbfef..7178412c 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/client.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/client.py @@ -115,6 +115,22 @@ def _get_default_mtls_endpoint(api_endpoint): DEFAULT_ENDPOINT ) + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ErrorStatsServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -127,7 +143,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): kwargs: Additional arguments to pass to the constructor. Returns: - {@api.name}: The constructed client. + ErrorStatsServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -230,10 +246,10 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.ErrorStatsServiceTransport]): The + transport (Union[str, ErrorStatsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (client_options_lib.ClientOptions): Custom options for the + client_options (google.api_core.client_options.ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT @@ -269,21 +285,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -326,7 +338,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) @@ -344,22 +356,23 @@ def list_group_stats( r"""Lists the specified groups. Args: - request (:class:`~.error_stats_service.ListGroupStatsRequest`): + request (google.cloud.errorreporting_v1beta1.types.ListGroupStatsRequest): The request object. Specifies a set of `ErrorGroupStats` to return. - project_name (:class:`str`): - Required. The resource name of the - Google Cloud Platform project. Written - as projects/ plus the Google - Cloud Platform project ID. - - Example: projects/my- - project-123. + project_name (str): + Required. The resource name of the Google Cloud Platform + project. Written as ``projects/{projectID}`` or + ``projects/{projectNumber}``, where ``{projectID}`` and + ``{projectNumber}`` can be found in the `Google Cloud + Console `__. + + Examples: ``projects/my-project-123``, + ``projects/5551234``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - time_range (:class:`~.error_stats_service.QueryTimeRange`): + time_range (google.cloud.errorreporting_v1beta1.types.QueryTimeRange): Optional. List data for the given time range. If not set, a default time range is used. The field time_range_begin in the response will specify the @@ -368,6 +381,7 @@ def list_group_stats( unless the request contains an explicit group_id list. If a group_id list is given, also ErrorGroupStats with zero occurrences are returned. + This corresponds to the ``time_range`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -379,7 +393,7 @@ def list_group_stats( sent along with the request as metadata. Returns: - ~.pagers.ListGroupStatsPager: + google.cloud.errorreporting_v1beta1.services.error_stats_service.pagers.ListGroupStatsPager: Contains a set of requested error group stats. Iterating over this object will yield @@ -449,21 +463,24 @@ def list_events( r"""Lists the specified events. Args: - request (:class:`~.error_stats_service.ListEventsRequest`): + request (google.cloud.errorreporting_v1beta1.types.ListEventsRequest): The request object. Specifies a set of error events to return. - project_name (:class:`str`): + project_name (str): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectID}``, where + ``{projectID}`` is the `Google Cloud Platform project ID `__. + Example: ``projects/my-project-123``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - group_id (:class:`str`): + group_id (str): Required. The group for which events shall be returned. + This corresponds to the ``group_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -475,7 +492,7 @@ def list_events( sent along with the request as metadata. Returns: - ~.pagers.ListEventsPager: + google.cloud.errorreporting_v1beta1.services.error_stats_service.pagers.ListEventsPager: Contains a set of requested error events. Iterating over this object will yield @@ -544,14 +561,16 @@ def delete_events( r"""Deletes all error events of a given project. Args: - request (:class:`~.error_stats_service.DeleteEventsRequest`): + request (google.cloud.errorreporting_v1beta1.types.DeleteEventsRequest): The request object. Deletes all events in the project. - project_name (:class:`str`): + project_name (str): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectID}``, where + ``{projectID}`` is the `Google Cloud Platform project ID `__. + Example: ``projects/my-project-123``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -563,7 +582,7 @@ def delete_events( sent along with the request as metadata. Returns: - ~.error_stats_service.DeleteEventsResponse: + google.cloud.errorreporting_v1beta1.types.DeleteEventsResponse: Response message for deleting error events. diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/pagers.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/pagers.py index 02a4faa4..a5d6c02f 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/pagers.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/pagers.py @@ -15,7 +15,16 @@ # limitations under the License. # -from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) from google.cloud.errorreporting_v1beta1.types import common from google.cloud.errorreporting_v1beta1.types import error_stats_service @@ -25,7 +34,7 @@ class ListGroupStatsPager: """A pager for iterating through ``list_group_stats`` requests. This class thinly wraps an initial - :class:`~.error_stats_service.ListGroupStatsResponse` object, and + :class:`google.cloud.errorreporting_v1beta1.types.ListGroupStatsResponse` object, and provides an ``__iter__`` method to iterate through its ``error_group_stats`` field. @@ -34,7 +43,7 @@ class ListGroupStatsPager: through the ``error_group_stats`` field on the corresponding responses. - All the usual :class:`~.error_stats_service.ListGroupStatsResponse` + All the usual :class:`google.cloud.errorreporting_v1beta1.types.ListGroupStatsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -52,9 +61,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.error_stats_service.ListGroupStatsRequest`): + request (google.cloud.errorreporting_v1beta1.types.ListGroupStatsRequest): The initial request object. - response (:class:`~.error_stats_service.ListGroupStatsResponse`): + response (google.cloud.errorreporting_v1beta1.types.ListGroupStatsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -87,7 +96,7 @@ class ListGroupStatsAsyncPager: """A pager for iterating through ``list_group_stats`` requests. This class thinly wraps an initial - :class:`~.error_stats_service.ListGroupStatsResponse` object, and + :class:`google.cloud.errorreporting_v1beta1.types.ListGroupStatsResponse` object, and provides an ``__aiter__`` method to iterate through its ``error_group_stats`` field. @@ -96,7 +105,7 @@ class ListGroupStatsAsyncPager: through the ``error_group_stats`` field on the corresponding responses. - All the usual :class:`~.error_stats_service.ListGroupStatsResponse` + All the usual :class:`google.cloud.errorreporting_v1beta1.types.ListGroupStatsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -114,9 +123,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.error_stats_service.ListGroupStatsRequest`): + request (google.cloud.errorreporting_v1beta1.types.ListGroupStatsRequest): The initial request object. - response (:class:`~.error_stats_service.ListGroupStatsResponse`): + response (google.cloud.errorreporting_v1beta1.types.ListGroupStatsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -153,7 +162,7 @@ class ListEventsPager: """A pager for iterating through ``list_events`` requests. This class thinly wraps an initial - :class:`~.error_stats_service.ListEventsResponse` object, and + :class:`google.cloud.errorreporting_v1beta1.types.ListEventsResponse` object, and provides an ``__iter__`` method to iterate through its ``error_events`` field. @@ -162,7 +171,7 @@ class ListEventsPager: through the ``error_events`` field on the corresponding responses. - All the usual :class:`~.error_stats_service.ListEventsResponse` + All the usual :class:`google.cloud.errorreporting_v1beta1.types.ListEventsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -180,9 +189,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.error_stats_service.ListEventsRequest`): + request (google.cloud.errorreporting_v1beta1.types.ListEventsRequest): The initial request object. - response (:class:`~.error_stats_service.ListEventsResponse`): + response (google.cloud.errorreporting_v1beta1.types.ListEventsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -215,7 +224,7 @@ class ListEventsAsyncPager: """A pager for iterating through ``list_events`` requests. This class thinly wraps an initial - :class:`~.error_stats_service.ListEventsResponse` object, and + :class:`google.cloud.errorreporting_v1beta1.types.ListEventsResponse` object, and provides an ``__aiter__`` method to iterate through its ``error_events`` field. @@ -224,7 +233,7 @@ class ListEventsAsyncPager: through the ``error_events`` field on the corresponding responses. - All the usual :class:`~.error_stats_service.ListEventsResponse` + All the usual :class:`google.cloud.errorreporting_v1beta1.types.ListEventsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -242,9 +251,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.error_stats_service.ListEventsRequest`): + request (google.cloud.errorreporting_v1beta1.types.ListEventsRequest): The initial request object. - response (:class:`~.error_stats_service.ListEventsResponse`): + response (google.cloud.errorreporting_v1beta1.types.ListEventsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py index f9595d23..6a5328c5 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py @@ -58,6 +58,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -88,6 +89,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -104,6 +109,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -113,11 +123,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -161,12 +166,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py index 4c687c11..336e180a 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py @@ -102,6 +102,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -133,6 +134,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -149,6 +154,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -158,11 +168,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -206,12 +211,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/google/cloud/errorreporting_v1beta1/services/report_errors_service/async_client.py b/google/cloud/errorreporting_v1beta1/services/report_errors_service/async_client.py index 3b7c6fcf..61f223b6 100644 --- a/google/cloud/errorreporting_v1beta1/services/report_errors_service/async_client.py +++ b/google/cloud/errorreporting_v1beta1/services/report_errors_service/async_client.py @@ -72,7 +72,36 @@ class ReportErrorsServiceAsyncClient: ReportErrorsServiceClient.parse_common_location_path ) - from_service_account_file = ReportErrorsServiceClient.from_service_account_file + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReportErrorsServiceAsyncClient: The constructed client. + """ + return ReportErrorsServiceClient.from_service_account_info.__func__(ReportErrorsServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReportErrorsServiceAsyncClient: The constructed client. + """ + return ReportErrorsServiceClient.from_service_account_file.__func__(ReportErrorsServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -147,31 +176,42 @@ async def report_error_event( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> report_errors_service.ReportErrorEventResponse: - r"""Report an individual error event. + r"""Report an individual error event and record the event to a log. This endpoint accepts **either** an OAuth token, **or** an `API key `__ for authentication. To use an API key, append it to the URL as the value of a ``key`` parameter. For example: - ``POST https://clouderrorreporting.googleapis.com/v1beta1/projects/example-project/events:report?key=123ABC456`` + ``POST https://clouderrorreporting.googleapis.com/v1beta1/{projectName}/events:report?key=123ABC456`` + + **Note:** `Error Reporting `__ is a global + service built on Cloud Logging and doesn't analyze logs stored + in regional log buckets or logs routed to other Google Cloud + projects. + + For more information, see `Using Error Reporting with + regionalized logs `__. Args: - request (:class:`~.report_errors_service.ReportErrorEventRequest`): + request (:class:`google.cloud.errorreporting_v1beta1.types.ReportErrorEventRequest`): The request object. A request for reporting an individual error event. project_name (:class:`str`): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectId}``, where + ``{projectId}`` is the `Google Cloud Platform project ID `__. - Example: ``projects/my-project-123``. + + Example: // ``projects/my-project-123``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - event (:class:`~.report_errors_service.ReportedErrorEvent`): + event (:class:`google.cloud.errorreporting_v1beta1.types.ReportedErrorEvent`): Required. The error event to be reported. + This corresponds to the ``event`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -183,7 +223,7 @@ async def report_error_event( sent along with the request as metadata. Returns: - ~.report_errors_service.ReportErrorEventResponse: + google.cloud.errorreporting_v1beta1.types.ReportErrorEventResponse: Response for reporting an individual error event. Data may be added to this message in the future. diff --git a/google/cloud/errorreporting_v1beta1/services/report_errors_service/client.py b/google/cloud/errorreporting_v1beta1/services/report_errors_service/client.py index b10ecca4..840e449f 100644 --- a/google/cloud/errorreporting_v1beta1/services/report_errors_service/client.py +++ b/google/cloud/errorreporting_v1beta1/services/report_errors_service/client.py @@ -111,6 +111,22 @@ def _get_default_mtls_endpoint(api_endpoint): DEFAULT_ENDPOINT ) + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReportErrorsServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -123,7 +139,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): kwargs: Additional arguments to pass to the constructor. Returns: - {@api.name}: The constructed client. + ReportErrorsServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -215,10 +231,10 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.ReportErrorsServiceTransport]): The + transport (Union[str, ReportErrorsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (client_options_lib.ClientOptions): Custom options for the + client_options (google.api_core.client_options.ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT @@ -254,21 +270,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -311,7 +323,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) @@ -326,31 +338,42 @@ def report_error_event( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> report_errors_service.ReportErrorEventResponse: - r"""Report an individual error event. + r"""Report an individual error event and record the event to a log. This endpoint accepts **either** an OAuth token, **or** an `API key `__ for authentication. To use an API key, append it to the URL as the value of a ``key`` parameter. For example: - ``POST https://clouderrorreporting.googleapis.com/v1beta1/projects/example-project/events:report?key=123ABC456`` + ``POST https://clouderrorreporting.googleapis.com/v1beta1/{projectName}/events:report?key=123ABC456`` + + **Note:** `Error Reporting `__ is a global + service built on Cloud Logging and doesn't analyze logs stored + in regional log buckets or logs routed to other Google Cloud + projects. + + For more information, see `Using Error Reporting with + regionalized logs `__. Args: - request (:class:`~.report_errors_service.ReportErrorEventRequest`): + request (google.cloud.errorreporting_v1beta1.types.ReportErrorEventRequest): The request object. A request for reporting an individual error event. - project_name (:class:`str`): + project_name (str): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectId}``, where + ``{projectId}`` is the `Google Cloud Platform project ID `__. - Example: ``projects/my-project-123``. + + Example: // ``projects/my-project-123``. + This corresponds to the ``project_name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - event (:class:`~.report_errors_service.ReportedErrorEvent`): + event (google.cloud.errorreporting_v1beta1.types.ReportedErrorEvent): Required. The error event to be reported. + This corresponds to the ``event`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -362,7 +385,7 @@ def report_error_event( sent along with the request as metadata. Returns: - ~.report_errors_service.ReportErrorEventResponse: + google.cloud.errorreporting_v1beta1.types.ReportErrorEventResponse: Response for reporting an individual error event. Data may be added to this message in the future. diff --git a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py index f2c84d92..f7eea171 100644 --- a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py +++ b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py @@ -57,6 +57,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -87,6 +88,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -103,6 +108,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -112,11 +122,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -160,12 +165,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ @@ -246,14 +257,22 @@ def report_error_event( ]: r"""Return a callable for the report error event method over gRPC. - Report an individual error event. + Report an individual error event and record the event to a log. This endpoint accepts **either** an OAuth token, **or** an `API key `__ for authentication. To use an API key, append it to the URL as the value of a ``key`` parameter. For example: - ``POST https://clouderrorreporting.googleapis.com/v1beta1/projects/example-project/events:report?key=123ABC456`` + ``POST https://clouderrorreporting.googleapis.com/v1beta1/{projectName}/events:report?key=123ABC456`` + + **Note:** `Error Reporting `__ is a global + service built on Cloud Logging and doesn't analyze logs stored + in regional log buckets or logs routed to other Google Cloud + projects. + + For more information, see `Using Error Reporting with + regionalized logs `__. Returns: Callable[[~.ReportErrorEventRequest], diff --git a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py index 39465e57..80327fd8 100644 --- a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py +++ b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py @@ -101,6 +101,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -132,6 +133,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -148,6 +153,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -157,11 +167,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -205,12 +210,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ @@ -250,14 +261,22 @@ def report_error_event( ]: r"""Return a callable for the report error event method over gRPC. - Report an individual error event. + Report an individual error event and record the event to a log. This endpoint accepts **either** an OAuth token, **or** an `API key `__ for authentication. To use an API key, append it to the URL as the value of a ``key`` parameter. For example: - ``POST https://clouderrorreporting.googleapis.com/v1beta1/projects/example-project/events:report?key=123ABC456`` + ``POST https://clouderrorreporting.googleapis.com/v1beta1/{projectName}/events:report?key=123ABC456`` + + **Note:** `Error Reporting `__ is a global + service built on Cloud Logging and doesn't analyze logs stored + in regional log buckets or logs routed to other Google Cloud + projects. + + For more information, see `Using Error Reporting with + regionalized logs `__. Returns: Callable[[~.ReportErrorEventRequest], diff --git a/google/cloud/errorreporting_v1beta1/types/__init__.py b/google/cloud/errorreporting_v1beta1/types/__init__.py index fc7243be..8819a78f 100644 --- a/google/cloud/errorreporting_v1beta1/types/__init__.py +++ b/google/cloud/errorreporting_v1beta1/types/__init__.py @@ -23,6 +23,7 @@ ErrorContext, HttpRequestContext, SourceLocation, + ResolutionStatus, ) from .error_group_service import ( GetGroupRequest, @@ -56,6 +57,7 @@ "ErrorContext", "HttpRequestContext", "SourceLocation", + "ResolutionStatus", "GetGroupRequest", "UpdateGroupRequest", "ListGroupStatsRequest", diff --git a/google/cloud/errorreporting_v1beta1/types/common.py b/google/cloud/errorreporting_v1beta1/types/common.py index 779aa453..e0d1a7eb 100644 --- a/google/cloud/errorreporting_v1beta1/types/common.py +++ b/google/cloud/errorreporting_v1beta1/types/common.py @@ -24,6 +24,7 @@ __protobuf__ = proto.module( package="google.devtools.clouderrorreporting.v1beta1", manifest={ + "ResolutionStatus", "ErrorGroup", "TrackingIssue", "ErrorEvent", @@ -35,6 +36,15 @@ ) +class ResolutionStatus(proto.Enum): + r"""Resolution status of an error group.""" + RESOLUTION_STATUS_UNSPECIFIED = 0 + OPEN = 1 + ACKNOWLEDGED = 2 + RESOLVED = 3 + MUTED = 4 + + class ErrorGroup(proto.Message): r"""Description of a group of similar error events. @@ -42,14 +52,18 @@ class ErrorGroup(proto.Message): name (str): The group resource name. Example: projects/my- - project-123/groups/my-groupid + project-123/groups/CNSgkpnppqKCUw group_id (str): Group IDs are unique for a given project. If the same kind of error occurs in different service contexts, it will receive the same group ID. - tracking_issues (Sequence[~.common.TrackingIssue]): + tracking_issues (Sequence[google.cloud.errorreporting_v1beta1.types.TrackingIssue]): Associated tracking issues. + resolution_status (google.cloud.errorreporting_v1beta1.types.ResolutionStatus): + Error group's resolution status. + An unspecified resolution status will be + interpreted as OPEN """ name = proto.Field(proto.STRING, number=1) @@ -60,6 +74,8 @@ class ErrorGroup(proto.Message): proto.MESSAGE, number=3, message="TrackingIssue", ) + resolution_status = proto.Field(proto.ENUM, number=5, enum="ResolutionStatus",) + class TrackingIssue(proto.Message): r"""Information related to tracking the progress on resolving the @@ -80,17 +96,17 @@ class ErrorEvent(proto.Message): system. Attributes: - event_time (~.timestamp.Timestamp): + event_time (google.protobuf.timestamp_pb2.Timestamp): Time when the event occurred as provided in the error report. If the report did not contain a timestamp, the time the error was received by the Error Reporting system is used. - service_context (~.common.ServiceContext): + service_context (google.cloud.errorreporting_v1beta1.types.ServiceContext): The ``ServiceContext`` for which this error was reported. message (str): The stack trace that was reported or logged by the service. - context (~.common.ErrorContext): + context (google.cloud.errorreporting_v1beta1.types.ErrorContext): Data about the context in which the error occurred. """ @@ -149,7 +165,7 @@ class ErrorContext(proto.Message): Engine logs. Attributes: - http_request (~.common.HttpRequestContext): + http_request (google.cloud.errorreporting_v1beta1.types.HttpRequestContext): The HTTP request which was processed when the error was triggered. user (str): @@ -160,7 +176,7 @@ class ErrorContext(proto.Message): this case the Error Reporting system will use other data, such as remote IP address, to distinguish affected users. See ``affected_users_count`` in ``ErrorGroupStats``. - report_location (~.common.SourceLocation): + report_location (google.cloud.errorreporting_v1beta1.types.SourceLocation): The location in the source code where the decision was made to report the error, usually the place where it was logged. For a logged diff --git a/google/cloud/errorreporting_v1beta1/types/error_group_service.py b/google/cloud/errorreporting_v1beta1/types/error_group_service.py index 70aa92a8..e36854b6 100644 --- a/google/cloud/errorreporting_v1beta1/types/error_group_service.py +++ b/google/cloud/errorreporting_v1beta1/types/error_group_service.py @@ -32,7 +32,7 @@ class GetGroupRequest(proto.Message): Attributes: group_name (str): - The group resource name. Written as + Required. The group resource name. Written as ``projects/{projectID}/groups/{group_name}``. Call ```groupStats.list`` `__ to return a list of groups belonging to this project. @@ -47,7 +47,7 @@ class UpdateGroupRequest(proto.Message): r"""A request to replace the existing data for the given group. Attributes: - group (~.common.ErrorGroup): + group (google.cloud.errorreporting_v1beta1.types.ErrorGroup): Required. The group which replaces the resource on the server. """ diff --git a/google/cloud/errorreporting_v1beta1/types/error_stats_service.py b/google/cloud/errorreporting_v1beta1/types/error_stats_service.py index 51a14e89..3973ca04 100644 --- a/google/cloud/errorreporting_v1beta1/types/error_stats_service.py +++ b/google/cloud/errorreporting_v1beta1/types/error_stats_service.py @@ -65,23 +65,23 @@ class ListGroupStatsRequest(proto.Message): Attributes: project_name (str): - Required. The resource name of the Google - Cloud Platform project. Written as - projects/ plus the Google - Cloud Platform project ID. + Required. The resource name of the Google Cloud Platform + project. Written as ``projects/{projectID}`` or + ``projects/{projectNumber}``, where ``{projectID}`` and + ``{projectNumber}`` can be found in the `Google Cloud + Console `__. - Example: projects/my-project-123. + Examples: ``projects/my-project-123``, ``projects/5551234``. group_id (Sequence[str]): Optional. List all ErrorGroupStats with these IDs. - service_filter (~.error_stats_service.ServiceContextFilter): + service_filter (google.cloud.errorreporting_v1beta1.types.ServiceContextFilter): Optional. List only ErrorGroupStats which belong to a service context that matches the filter. Data for all service contexts is returned if this field is not specified. - time_range (~.error_stats_service.QueryTimeRange): + time_range (google.cloud.errorreporting_v1beta1.types.QueryTimeRange): Optional. List data for the given time range. If not set, a default time range is used. The field time_range_begin in the response will specify the beginning of this time range. @@ -89,17 +89,17 @@ class ListGroupStatsRequest(proto.Message): range are returned, unless the request contains an explicit group_id list. If a group_id list is given, also ErrorGroupStats with zero occurrences are returned. - timed_count_duration (~.duration.Duration): + timed_count_duration (google.protobuf.duration_pb2.Duration): Optional. The preferred duration for a single returned ``TimedCount``. If not set, no timed counts are returned. - alignment (~.error_stats_service.TimedCountAlignment): + alignment (google.cloud.errorreporting_v1beta1.types.TimedCountAlignment): Optional. The alignment of the timed counts to be returned. Default is ``ALIGNMENT_EQUAL_AT_END``. - alignment_time (~.timestamp.Timestamp): + alignment_time (google.protobuf.timestamp_pb2.Timestamp): Optional. Time where the timed counts shall be aligned if rounded alignment is chosen. Default is 00:00 UTC. - order (~.error_stats_service.ErrorGroupOrder): + order (google.cloud.errorreporting_v1beta1.types.ErrorGroupOrder): Optional. The sort order in which the results are returned. Default is ``COUNT_DESC``. page_size (int): @@ -140,7 +140,7 @@ class ListGroupStatsResponse(proto.Message): r"""Contains a set of requested error group stats. Attributes: - error_group_stats (Sequence[~.error_stats_service.ErrorGroupStats]): + error_group_stats (Sequence[google.cloud.errorreporting_v1beta1.types.ErrorGroupStats]): The error group stats which match the given request. next_page_token (str): @@ -148,7 +148,7 @@ class ListGroupStatsResponse(proto.Message): Pass this token, along with the same query parameters as the first request, to view the next page of results. - time_range_begin (~.timestamp.Timestamp): + time_range_begin (google.protobuf.timestamp_pb2.Timestamp): The timestamp specifies the start time to which the request was restricted. The start time is set based on the requested time range. It may @@ -177,7 +177,7 @@ class ErrorGroupStats(proto.Message): criteria, such as a given time period and/or service filter. Attributes: - group (~.common.ErrorGroup): + group (google.cloud.errorreporting_v1beta1.types.ErrorGroup): Group data that is independent of the filter criteria. count (int): @@ -195,22 +195,22 @@ class ErrorGroupStats(proto.Message): provided in the error report. If more users are implicitly affected, such as due to a crash of the whole service, this is not reflected here. - timed_counts (Sequence[~.error_stats_service.TimedCount]): + timed_counts (Sequence[google.cloud.errorreporting_v1beta1.types.TimedCount]): Approximate number of occurrences over time. Timed counts returned by ListGroups are guaranteed to be: - Inside the requested time interval - Non-overlapping, and - Ordered by ascending time. - first_seen_time (~.timestamp.Timestamp): + first_seen_time (google.protobuf.timestamp_pb2.Timestamp): Approximate first occurrence that was ever seen for this group and which matches the given filter criteria, ignoring the time_range that was specified in the request. - last_seen_time (~.timestamp.Timestamp): + last_seen_time (google.protobuf.timestamp_pb2.Timestamp): Approximate last occurrence that was ever seen for this group and which matches the given filter criteria, ignoring the time_range that was specified in the request. - affected_services (Sequence[~.common.ServiceContext]): + affected_services (Sequence[google.cloud.errorreporting_v1beta1.types.ServiceContext]): Service contexts with a non-zero error count for the given filter criteria. This list can be truncated if multiple services are affected. Refer to ``num_affected_services`` @@ -218,7 +218,7 @@ class ErrorGroupStats(proto.Message): num_affected_services (int): The total number of services with a non-zero error count for the given filter criteria. - representative (~.common.ErrorEvent): + representative (google.cloud.errorreporting_v1beta1.types.ErrorEvent): An arbitrary event that is chosen as representative for the whole group. The representative event is intended to be used as a @@ -259,10 +259,10 @@ class TimedCount(proto.Message): count (int): Approximate number of occurrences in the given time period. - start_time (~.timestamp.Timestamp): + start_time (google.protobuf.timestamp_pb2.Timestamp): Start of the time period to which ``count`` refers (included). - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): End of the time period to which ``count`` refers (excluded). """ @@ -279,19 +279,20 @@ class ListEventsRequest(proto.Message): Attributes: project_name (str): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectID}``, where + ``{projectID}`` is the `Google Cloud Platform project ID `__. + Example: ``projects/my-project-123``. group_id (str): Required. The group for which events shall be returned. - service_filter (~.error_stats_service.ServiceContextFilter): + service_filter (google.cloud.errorreporting_v1beta1.types.ServiceContextFilter): Optional. List only ErrorGroups which belong to a service context that matches the filter. Data for all service contexts is returned if this field is not specified. - time_range (~.error_stats_service.QueryTimeRange): + time_range (google.cloud.errorreporting_v1beta1.types.QueryTimeRange): Optional. List only data for the given time range. If not set a default time range is used. The field time_range_begin in the response will specify the beginning of this time @@ -323,7 +324,7 @@ class ListEventsResponse(proto.Message): r"""Contains a set of requested error events. Attributes: - error_events (Sequence[~.common.ErrorEvent]): + error_events (Sequence[google.cloud.errorreporting_v1beta1.types.ErrorEvent]): The error events which match the given request. next_page_token (str): @@ -331,7 +332,7 @@ class ListEventsResponse(proto.Message): Pass this token, along with the same query parameters as the first request, to view the next page of results. - time_range_begin (~.timestamp.Timestamp): + time_range_begin (google.protobuf.timestamp_pb2.Timestamp): The timestamp specifies the start time to which the request was restricted. """ @@ -356,7 +357,7 @@ class QueryTimeRange(proto.Message): durations might be adjusted for lower durations. Attributes: - period (~.error_stats_service.QueryTimeRange.Period): + period (google.cloud.errorreporting_v1beta1.types.QueryTimeRange.Period): Restricts the query to the specified time range. """ @@ -404,9 +405,10 @@ class DeleteEventsRequest(proto.Message): Attributes: project_name (str): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectID}``, where + ``{projectID}`` is the `Google Cloud Platform project ID `__. + Example: ``projects/my-project-123``. """ diff --git a/google/cloud/errorreporting_v1beta1/types/report_errors_service.py b/google/cloud/errorreporting_v1beta1/types/report_errors_service.py index 1a66727b..bdba6ee8 100644 --- a/google/cloud/errorreporting_v1beta1/types/report_errors_service.py +++ b/google/cloud/errorreporting_v1beta1/types/report_errors_service.py @@ -38,11 +38,12 @@ class ReportErrorEventRequest(proto.Message): Attributes: project_name (str): Required. The resource name of the Google Cloud Platform - project. Written as ``projects/`` plus the `Google Cloud - Platform project + project. Written as ``projects/{projectId}``, where + ``{projectId}`` is the `Google Cloud Platform project ID `__. - Example: ``projects/my-project-123``. - event (~.report_errors_service.ReportedErrorEvent): + + Example: // ``projects/my-project-123``. + event (google.cloud.errorreporting_v1beta1.types.ReportedErrorEvent): Required. The error event to be reported. """ @@ -62,12 +63,12 @@ class ReportedErrorEvent(proto.Message): system. Attributes: - event_time (~.timestamp.Timestamp): + event_time (google.protobuf.timestamp_pb2.Timestamp): Optional. Time when the event occurred. If not provided, the time when the event was received by the Error Reporting system will be used. - service_context (~.common.ServiceContext): + service_context (google.cloud.errorreporting_v1beta1.types.ServiceContext): Required. The service context in which this error has occurred. message (str): @@ -96,7 +97,7 @@ class ReportedErrorEvent(proto.Message): ```(string)$exception`` `__. - **Go**: Must be the return value of ```runtime.Stack()`` `__. - context (~.common.ErrorContext): + context (google.cloud.errorreporting_v1beta1.types.ErrorContext): Optional. A description of the context in which the error occurred. """ diff --git a/synth.metadata b/synth.metadata index f49b243b..377f5974 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,15 +4,15 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-error-reporting.git", - "sha": "eaf4a5aebe9f3cee0af211defec7ff10d5bae4a4" + "sha": "c4b168d1f4e045d72487abba88e118a15b1c99ef" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "dd372aa22ded7a8ba6f0e03a80e06358a3fa0907", - "internalRef": "347055288" + "sha": "f6dd7e47620566925a4b3f1ce029e74e1b2f2516", + "internalRef": "359781040" } }, { @@ -42,6 +42,7 @@ } ], "generatedFiles": [ + ".coveragerc", ".flake8", ".github/CONTRIBUTING.md", ".github/ISSUE_TEMPLATE/bug_report.md", @@ -95,6 +96,9 @@ "docs/_static/custom.css", "docs/_templates/layout.html", "docs/conf.py", + "docs/errorreporting_v1beta1/error_group_service.rst", + "docs/errorreporting_v1beta1/error_stats_service.rst", + "docs/errorreporting_v1beta1/report_errors_service.rst", "docs/errorreporting_v1beta1/services.rst", "docs/errorreporting_v1beta1/types.rst", "docs/multiprocessing.rst", diff --git a/tests/unit/gapic/errorreporting_v1beta1/__init__.py b/tests/unit/gapic/errorreporting_v1beta1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/errorreporting_v1beta1/__init__.py +++ b/tests/unit/gapic/errorreporting_v1beta1/__init__.py @@ -1 +1,16 @@ +# -*- 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 +# +# 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. +# diff --git a/tests/unit/gapic/errorreporting_v1beta1/test_error_group_service.py b/tests/unit/gapic/errorreporting_v1beta1/test_error_group_service.py index da93c3df..814cefe8 100644 --- a/tests/unit/gapic/errorreporting_v1beta1/test_error_group_service.py +++ b/tests/unit/gapic/errorreporting_v1beta1/test_error_group_service.py @@ -90,7 +90,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [ErrorGroupServiceClient, ErrorGroupServiceAsyncClient] + "client_class", [ErrorGroupServiceClient, ErrorGroupServiceAsyncClient,] +) +def test_error_group_service_client_from_service_account_info(client_class): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "clouderrorreporting.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [ErrorGroupServiceClient, ErrorGroupServiceAsyncClient,] ) def test_error_group_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -100,16 +117,21 @@ def test_error_group_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "clouderrorreporting.googleapis.com:443" def test_error_group_service_client_get_transport_class(): transport = ErrorGroupServiceClient.get_transport_class() - assert transport == transports.ErrorGroupServiceGrpcTransport + available_transports = [ + transports.ErrorGroupServiceGrpcTransport, + ] + assert transport in available_transports transport = ErrorGroupServiceClient.get_transport_class("grpc") assert transport == transports.ErrorGroupServiceGrpcTransport @@ -160,7 +182,7 @@ def test_error_group_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -176,7 +198,7 @@ def test_error_group_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -192,7 +214,7 @@ def test_error_group_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -220,7 +242,7 @@ def test_error_group_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -281,29 +303,25 @@ def test_error_group_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -312,66 +330,53 @@ def test_error_group_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback - # Check the case client_cert_source and ADC client cert are not provided. - with mock.patch.dict( - os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} - ): - with mock.patch.object(transport_class, "__init__") as patched: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -397,7 +402,7 @@ def test_error_group_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -427,7 +432,7 @@ def test_error_group_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -446,7 +451,7 @@ def test_error_group_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -467,7 +472,9 @@ def test_get_group( with mock.patch.object(type(client.transport.get_group), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = common.ErrorGroup( - name="name_value", group_id="group_id_value", + name="name_value", + group_id="group_id_value", + resolution_status=common.ResolutionStatus.OPEN, ) response = client.get_group(request) @@ -486,11 +493,29 @@ def test_get_group( assert response.group_id == "group_id_value" + assert response.resolution_status == common.ResolutionStatus.OPEN + def test_get_group_from_dict(): test_get_group(request_type=dict) +def test_get_group_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ErrorGroupServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_group), "__call__") as call: + client.get_group() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == error_group_service.GetGroupRequest() + + @pytest.mark.asyncio async def test_get_group_async( transport: str = "grpc_asyncio", request_type=error_group_service.GetGroupRequest @@ -507,7 +532,11 @@ async def test_get_group_async( with mock.patch.object(type(client.transport.get_group), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - common.ErrorGroup(name="name_value", group_id="group_id_value",) + common.ErrorGroup( + name="name_value", + group_id="group_id_value", + resolution_status=common.ResolutionStatus.OPEN, + ) ) response = await client.get_group(request) @@ -525,6 +554,8 @@ async def test_get_group_async( assert response.group_id == "group_id_value" + assert response.resolution_status == common.ResolutionStatus.OPEN + @pytest.mark.asyncio async def test_get_group_async_from_dict(): @@ -666,7 +697,9 @@ def test_update_group( with mock.patch.object(type(client.transport.update_group), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = common.ErrorGroup( - name="name_value", group_id="group_id_value", + name="name_value", + group_id="group_id_value", + resolution_status=common.ResolutionStatus.OPEN, ) response = client.update_group(request) @@ -685,11 +718,29 @@ def test_update_group( assert response.group_id == "group_id_value" + assert response.resolution_status == common.ResolutionStatus.OPEN + def test_update_group_from_dict(): test_update_group(request_type=dict) +def test_update_group_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ErrorGroupServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_group), "__call__") as call: + client.update_group() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == error_group_service.UpdateGroupRequest() + + @pytest.mark.asyncio async def test_update_group_async( transport: str = "grpc_asyncio", request_type=error_group_service.UpdateGroupRequest @@ -706,7 +757,11 @@ async def test_update_group_async( with mock.patch.object(type(client.transport.update_group), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - common.ErrorGroup(name="name_value", group_id="group_id_value",) + common.ErrorGroup( + name="name_value", + group_id="group_id_value", + resolution_status=common.ResolutionStatus.OPEN, + ) ) response = await client.update_group(request) @@ -724,6 +779,8 @@ async def test_update_group_async( assert response.group_id == "group_id_value" + assert response.resolution_status == common.ResolutionStatus.OPEN + @pytest.mark.asyncio async def test_update_group_async_from_dict(): @@ -1014,6 +1071,53 @@ def test_error_group_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.ErrorGroupServiceGrpcTransport, + transports.ErrorGroupServiceGrpcAsyncIOTransport, + ], +) +def test_error_group_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + def test_error_group_service_host_no_port(): client = ErrorGroupServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1035,7 +1139,7 @@ def test_error_group_service_host_with_port(): def test_error_group_service_grpc_transport_channel(): - channel = grpc.insecure_channel("http://localhost/") + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ErrorGroupServiceGrpcTransport( @@ -1047,7 +1151,7 @@ def test_error_group_service_grpc_transport_channel(): def test_error_group_service_grpc_asyncio_transport_channel(): - channel = aio.insecure_channel("http://localhost/") + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ErrorGroupServiceGrpcAsyncIOTransport( @@ -1058,6 +1162,8 @@ def test_error_group_service_grpc_asyncio_transport_channel(): assert transport._ssl_channel_credentials == None +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -1072,7 +1178,7 @@ def test_error_group_service_transport_channel_mtls_with_client_cert_source( "grpc.ssl_channel_credentials", autospec=True ) as grpc_ssl_channel_cred: with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_ssl_cred = mock.Mock() grpc_ssl_channel_cred.return_value = mock_ssl_cred @@ -1110,6 +1216,8 @@ def test_error_group_service_transport_channel_mtls_with_client_cert_source( assert transport._ssl_channel_credentials == mock_ssl_cred +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -1125,7 +1233,7 @@ def test_error_group_service_transport_channel_mtls_with_adc(transport_class): ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel diff --git a/tests/unit/gapic/errorreporting_v1beta1/test_error_stats_service.py b/tests/unit/gapic/errorreporting_v1beta1/test_error_stats_service.py index 2ea69420..1966becb 100644 --- a/tests/unit/gapic/errorreporting_v1beta1/test_error_stats_service.py +++ b/tests/unit/gapic/errorreporting_v1beta1/test_error_stats_service.py @@ -93,7 +93,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [ErrorStatsServiceClient, ErrorStatsServiceAsyncClient] + "client_class", [ErrorStatsServiceClient, ErrorStatsServiceAsyncClient,] +) +def test_error_stats_service_client_from_service_account_info(client_class): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "clouderrorreporting.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [ErrorStatsServiceClient, ErrorStatsServiceAsyncClient,] ) def test_error_stats_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -103,16 +120,21 @@ def test_error_stats_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "clouderrorreporting.googleapis.com:443" def test_error_stats_service_client_get_transport_class(): transport = ErrorStatsServiceClient.get_transport_class() - assert transport == transports.ErrorStatsServiceGrpcTransport + available_transports = [ + transports.ErrorStatsServiceGrpcTransport, + ] + assert transport in available_transports transport = ErrorStatsServiceClient.get_transport_class("grpc") assert transport == transports.ErrorStatsServiceGrpcTransport @@ -163,7 +185,7 @@ def test_error_stats_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -179,7 +201,7 @@ def test_error_stats_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -195,7 +217,7 @@ def test_error_stats_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -223,7 +245,7 @@ def test_error_stats_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -284,29 +306,25 @@ def test_error_stats_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -315,66 +333,53 @@ def test_error_stats_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback - # Check the case client_cert_source and ADC client cert are not provided. - with mock.patch.dict( - os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} - ): - with mock.patch.object(transport_class, "__init__") as patched: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -400,7 +405,7 @@ def test_error_stats_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -430,7 +435,7 @@ def test_error_stats_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -449,7 +454,7 @@ def test_error_stats_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -492,6 +497,22 @@ def test_list_group_stats_from_dict(): test_list_group_stats(request_type=dict) +def test_list_group_stats_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ErrorStatsServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_group_stats), "__call__") as call: + client.list_group_stats() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == error_stats_service.ListGroupStatsRequest() + + @pytest.mark.asyncio async def test_list_group_stats_async( transport: str = "grpc_asyncio", @@ -888,6 +909,22 @@ def test_list_events_from_dict(): test_list_events(request_type=dict) +def test_list_events_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ErrorStatsServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_events), "__call__") as call: + client.list_events() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == error_stats_service.ListEventsRequest() + + @pytest.mark.asyncio async def test_list_events_async( transport: str = "grpc_asyncio", request_type=error_stats_service.ListEventsRequest @@ -1247,6 +1284,22 @@ def test_delete_events_from_dict(): test_delete_events(request_type=dict) +def test_delete_events_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ErrorStatsServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_events), "__call__") as call: + client.delete_events() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == error_stats_service.DeleteEventsRequest() + + @pytest.mark.asyncio async def test_delete_events_async( transport: str = "grpc_asyncio", @@ -1575,6 +1628,53 @@ def test_error_stats_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.ErrorStatsServiceGrpcTransport, + transports.ErrorStatsServiceGrpcAsyncIOTransport, + ], +) +def test_error_stats_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + def test_error_stats_service_host_no_port(): client = ErrorStatsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1596,7 +1696,7 @@ def test_error_stats_service_host_with_port(): def test_error_stats_service_grpc_transport_channel(): - channel = grpc.insecure_channel("http://localhost/") + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ErrorStatsServiceGrpcTransport( @@ -1608,7 +1708,7 @@ def test_error_stats_service_grpc_transport_channel(): def test_error_stats_service_grpc_asyncio_transport_channel(): - channel = aio.insecure_channel("http://localhost/") + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ErrorStatsServiceGrpcAsyncIOTransport( @@ -1619,6 +1719,8 @@ def test_error_stats_service_grpc_asyncio_transport_channel(): assert transport._ssl_channel_credentials == None +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -1633,7 +1735,7 @@ def test_error_stats_service_transport_channel_mtls_with_client_cert_source( "grpc.ssl_channel_credentials", autospec=True ) as grpc_ssl_channel_cred: with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_ssl_cred = mock.Mock() grpc_ssl_channel_cred.return_value = mock_ssl_cred @@ -1671,6 +1773,8 @@ def test_error_stats_service_transport_channel_mtls_with_client_cert_source( assert transport._ssl_channel_credentials == mock_ssl_cred +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -1686,7 +1790,7 @@ def test_error_stats_service_transport_channel_mtls_with_adc(transport_class): ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel diff --git a/tests/unit/gapic/errorreporting_v1beta1/test_report_errors_service.py b/tests/unit/gapic/errorreporting_v1beta1/test_report_errors_service.py index f84d267f..98a83947 100644 --- a/tests/unit/gapic/errorreporting_v1beta1/test_report_errors_service.py +++ b/tests/unit/gapic/errorreporting_v1beta1/test_report_errors_service.py @@ -93,7 +93,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [ReportErrorsServiceClient, ReportErrorsServiceAsyncClient] + "client_class", [ReportErrorsServiceClient, ReportErrorsServiceAsyncClient,] +) +def test_report_errors_service_client_from_service_account_info(client_class): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "clouderrorreporting.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [ReportErrorsServiceClient, ReportErrorsServiceAsyncClient,] ) def test_report_errors_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -103,16 +120,21 @@ def test_report_errors_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "clouderrorreporting.googleapis.com:443" def test_report_errors_service_client_get_transport_class(): transport = ReportErrorsServiceClient.get_transport_class() - assert transport == transports.ReportErrorsServiceGrpcTransport + available_transports = [ + transports.ReportErrorsServiceGrpcTransport, + ] + assert transport in available_transports transport = ReportErrorsServiceClient.get_transport_class("grpc") assert transport == transports.ReportErrorsServiceGrpcTransport @@ -167,7 +189,7 @@ def test_report_errors_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -183,7 +205,7 @@ def test_report_errors_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -199,7 +221,7 @@ def test_report_errors_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -227,7 +249,7 @@ def test_report_errors_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -288,29 +310,25 @@ def test_report_errors_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -319,66 +337,53 @@ def test_report_errors_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback - # Check the case client_cert_source and ADC client cert are not provided. - with mock.patch.dict( - os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} - ): - with mock.patch.object(transport_class, "__init__") as patched: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -408,7 +413,7 @@ def test_report_errors_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -442,7 +447,7 @@ def test_report_errors_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -461,7 +466,7 @@ def test_report_errors_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -502,6 +507,24 @@ def test_report_error_event_from_dict(): test_report_error_event(request_type=dict) +def test_report_error_event_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ReportErrorsServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.report_error_event), "__call__" + ) as call: + client.report_error_event() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == report_errors_service.ReportErrorEventRequest() + + @pytest.mark.asyncio async def test_report_error_event_async( transport: str = "grpc_asyncio", @@ -860,6 +883,53 @@ def test_report_errors_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.ReportErrorsServiceGrpcTransport, + transports.ReportErrorsServiceGrpcAsyncIOTransport, + ], +) +def test_report_errors_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + def test_report_errors_service_host_no_port(): client = ReportErrorsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -881,7 +951,7 @@ def test_report_errors_service_host_with_port(): def test_report_errors_service_grpc_transport_channel(): - channel = grpc.insecure_channel("http://localhost/") + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ReportErrorsServiceGrpcTransport( @@ -893,7 +963,7 @@ def test_report_errors_service_grpc_transport_channel(): def test_report_errors_service_grpc_asyncio_transport_channel(): - channel = aio.insecure_channel("http://localhost/") + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ReportErrorsServiceGrpcAsyncIOTransport( @@ -904,6 +974,8 @@ def test_report_errors_service_grpc_asyncio_transport_channel(): assert transport._ssl_channel_credentials == None +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -918,7 +990,7 @@ def test_report_errors_service_transport_channel_mtls_with_client_cert_source( "grpc.ssl_channel_credentials", autospec=True ) as grpc_ssl_channel_cred: with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_ssl_cred = mock.Mock() grpc_ssl_channel_cred.return_value = mock_ssl_cred @@ -956,6 +1028,8 @@ def test_report_errors_service_transport_channel_mtls_with_client_cert_source( assert transport._ssl_channel_credentials == mock_ssl_cred +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -971,7 +1045,7 @@ def test_report_errors_service_transport_channel_mtls_with_adc(transport_class): ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel From 7c8a430bf228175d9b420ee72330310b07607c3c Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 31 Mar 2021 15:14:50 -0700 Subject: [PATCH 09/13] chore: Re-generated to pick up changes from self (#72) --- synth.metadata | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synth.metadata b/synth.metadata index 377f5974..adab2bda 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-error-reporting.git", - "sha": "c4b168d1f4e045d72487abba88e118a15b1c99ef" + "sha": "511be86d97804b6ae4bee0718dde5fde21bddb49" } }, { From 9568d1d4778abb1827bf26cca3f355d9354a0bfa Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 1 Apr 2021 14:19:09 -0700 Subject: [PATCH 10/13] test: use constraints files to test lower bounds (#97) --- .kokoro/samples/python3.6/periodic-head.cfg | 11 ++ .kokoro/samples/python3.7/periodic-head.cfg | 11 ++ .kokoro/samples/python3.8/periodic-head.cfg | 11 ++ .kokoro/test-samples-against-head.sh | 28 ++++ .kokoro/test-samples-impl.sh | 102 ++++++++++++++ .kokoro/test-samples.sh | 96 +++---------- .../error_group_service/transports/base.py | 18 +-- .../error_group_service/transports/grpc.py | 101 +++++--------- .../transports/grpc_asyncio.py | 109 ++++++--------- .../error_stats_service/transports/base.py | 18 +-- .../error_stats_service/transports/grpc.py | 101 +++++--------- .../transports/grpc_asyncio.py | 109 ++++++--------- .../report_errors_service/transports/base.py | 18 +-- .../report_errors_service/transports/grpc.py | 101 +++++--------- .../transports/grpc_asyncio.py | 109 ++++++--------- .../errorreporting_v1beta1/types/__init__.py | 44 +++--- noxfile.py | 35 +++-- renovate.json | 3 +- setup.py | 3 +- synth.metadata | 129 +----------------- synth.py | 6 +- testing/constraints-3.6.txt | 3 +- 22 files changed, 496 insertions(+), 670 deletions(-) create mode 100644 .kokoro/samples/python3.6/periodic-head.cfg create mode 100644 .kokoro/samples/python3.7/periodic-head.cfg create mode 100644 .kokoro/samples/python3.8/periodic-head.cfg create mode 100755 .kokoro/test-samples-against-head.sh create mode 100755 .kokoro/test-samples-impl.sh diff --git a/.kokoro/samples/python3.6/periodic-head.cfg b/.kokoro/samples/python3.6/periodic-head.cfg new file mode 100644 index 00000000..f9cfcd33 --- /dev/null +++ b/.kokoro/samples/python3.6/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.7/periodic-head.cfg b/.kokoro/samples/python3.7/periodic-head.cfg new file mode 100644 index 00000000..f9cfcd33 --- /dev/null +++ b/.kokoro/samples/python3.7/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.8/periodic-head.cfg b/.kokoro/samples/python3.8/periodic-head.cfg new file mode 100644 index 00000000..f9cfcd33 --- /dev/null +++ b/.kokoro/samples/python3.8/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/test-samples-against-head.sh b/.kokoro/test-samples-against-head.sh new file mode 100755 index 00000000..320a9129 --- /dev/null +++ b/.kokoro/test-samples-against-head.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# 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. + +# A customized test runner for samples. +# +# For periodic builds, you can specify this file for testing against head. + +# `-e` enables the script to automatically fail when a command fails +# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero +set -eo pipefail +# Enables `**` to include files nested inside sub-folders +shopt -s globstar + +cd github/python-error-reporting + +exec .kokoro/test-samples-impl.sh diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh new file mode 100755 index 00000000..cf5de74c --- /dev/null +++ b/.kokoro/test-samples-impl.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Copyright 2021 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. + + +# `-e` enables the script to automatically fail when a command fails +# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero +set -eo pipefail +# Enables `**` to include files nested inside sub-folders +shopt -s globstar + +# Exit early if samples directory doesn't exist +if [ ! -d "./samples" ]; then + echo "No tests run. `./samples` not found" + exit 0 +fi + +# Disable buffering, so that the logs stream through. +export PYTHONUNBUFFERED=1 + +# Debug: show build environment +env | grep KOKORO + +# Install nox +python3.6 -m pip install --upgrade --quiet nox + +# Use secrets acessor service account to get secrets +if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then + gcloud auth activate-service-account \ + --key-file="${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" \ + --project="cloud-devrel-kokoro-resources" +fi + +# This script will create 3 files: +# - testing/test-env.sh +# - testing/service-account.json +# - testing/client-secrets.json +./scripts/decrypt-secrets.sh + +source ./testing/test-env.sh +export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/testing/service-account.json + +# For cloud-run session, we activate the service account for gcloud sdk. +gcloud auth activate-service-account \ + --key-file "${GOOGLE_APPLICATION_CREDENTIALS}" + +export GOOGLE_CLIENT_SECRETS=$(pwd)/testing/client-secrets.json + +echo -e "\n******************** TESTING PROJECTS ********************" + +# Switch to 'fail at end' to allow all tests to complete before exiting. +set +e +# Use RTN to return a non-zero value if the test fails. +RTN=0 +ROOT=$(pwd) +# Find all requirements.txt in the samples directory (may break on whitespace). +for file in samples/**/requirements.txt; do + cd "$ROOT" + # Navigate to the project folder. + file=$(dirname "$file") + cd "$file" + + echo "------------------------------------------------------------" + echo "- testing $file" + echo "------------------------------------------------------------" + + # Use nox to execute the tests for the project. + python3.6 -m nox -s "$RUN_TESTS_SESSION" + EXIT=$? + + # If this is a periodic build, send the test log to the FlakyBot. + # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. + if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + fi + + if [[ $EXIT -ne 0 ]]; then + RTN=1 + echo -e "\n Testing failed: Nox returned a non-zero exit code. \n" + else + echo -e "\n Testing completed.\n" + fi + +done +cd "$ROOT" + +# Workaround for Kokoro permissions issue: delete secrets +rm testing/{test-env.sh,client-secrets.json,service-account.json} + +exit "$RTN" diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index dfbbc8de..fefd09c5 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# The default test runner for samples. +# +# For periodic builds, we rewinds the repo to the latest release, and +# run test-samples-impl.sh. # `-e` enables the script to automatically fail when a command fails # `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero @@ -24,87 +28,19 @@ cd github/python-error-reporting # Run periodic samples tests at latest release if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + # preserving the test runner implementation. + cp .kokoro/test-samples-impl.sh "${TMPDIR}/test-samples-impl.sh" + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + echo "Now we rewind the repo back to the latest release..." LATEST_RELEASE=$(git describe --abbrev=0 --tags) git checkout $LATEST_RELEASE -fi - -# Exit early if samples directory doesn't exist -if [ ! -d "./samples" ]; then - echo "No tests run. `./samples` not found" - exit 0 -fi - -# Disable buffering, so that the logs stream through. -export PYTHONUNBUFFERED=1 - -# Debug: show build environment -env | grep KOKORO - -# Install nox -python3.6 -m pip install --upgrade --quiet nox - -# Use secrets acessor service account to get secrets -if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then - gcloud auth activate-service-account \ - --key-file="${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" \ - --project="cloud-devrel-kokoro-resources" -fi - -# This script will create 3 files: -# - testing/test-env.sh -# - testing/service-account.json -# - testing/client-secrets.json -./scripts/decrypt-secrets.sh - -source ./testing/test-env.sh -export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/testing/service-account.json - -# For cloud-run session, we activate the service account for gcloud sdk. -gcloud auth activate-service-account \ - --key-file "${GOOGLE_APPLICATION_CREDENTIALS}" - -export GOOGLE_CLIENT_SECRETS=$(pwd)/testing/client-secrets.json - -echo -e "\n******************** TESTING PROJECTS ********************" - -# Switch to 'fail at end' to allow all tests to complete before exiting. -set +e -# Use RTN to return a non-zero value if the test fails. -RTN=0 -ROOT=$(pwd) -# Find all requirements.txt in the samples directory (may break on whitespace). -for file in samples/**/requirements.txt; do - cd "$ROOT" - # Navigate to the project folder. - file=$(dirname "$file") - cd "$file" - - echo "------------------------------------------------------------" - echo "- testing $file" - echo "------------------------------------------------------------" - - # Use nox to execute the tests for the project. - python3.6 -m nox -s "$RUN_TESTS_SESSION" - EXIT=$? - - # If this is a periodic build, send the test log to the FlakyBot. - # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. - if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then - chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot - $KOKORO_GFILE_DIR/linux_amd64/flakybot + echo "The current head is: " + echo $(git rev-parse --verify HEAD) + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + # move back the test runner implementation if there's no file. + if [ ! -f .kokoro/test-samples-impl.sh ]; then + cp "${TMPDIR}/test-samples-impl.sh" .kokoro/test-samples-impl.sh fi +fi - if [[ $EXIT -ne 0 ]]; then - RTN=1 - echo -e "\n Testing failed: Nox returned a non-zero exit code. \n" - else - echo -e "\n Testing completed.\n" - fi - -done -cd "$ROOT" - -# Workaround for Kokoro permissions issue: delete secrets -rm testing/{test-env.sh,client-secrets.json,service-account.json} - -exit "$RTN" +exec .kokoro/test-samples-impl.sh diff --git a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/base.py b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/base.py index 794cf769..45260605 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/base.py +++ b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/base.py @@ -70,10 +70,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -81,6 +81,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -90,20 +93,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py index b6a71e1f..8514d3d7 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py +++ b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py @@ -107,7 +107,9 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -115,70 +117,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) - else: - ssl_credentials = SslCredentials().ssl_credentials - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -186,17 +168,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -210,7 +183,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py index 6fd73663..d09a346b 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py +++ b/google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py @@ -62,7 +62,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -140,10 +140,10 @@ def __init__( ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -152,7 +152,9 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -160,70 +162,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) - else: - ssl_credentials = SslCredentials().ssl_credentials - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -231,17 +213,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/base.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/base.py index 9ee79c34..18470b15 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/base.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/base.py @@ -69,10 +69,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -80,6 +80,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -89,20 +92,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py index 6a5328c5..1e033169 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py @@ -107,7 +107,9 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -115,70 +117,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) - else: - ssl_credentials = SslCredentials().ssl_credentials - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -186,17 +168,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -210,7 +183,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py index 336e180a..402abb49 100644 --- a/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py +++ b/google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py @@ -62,7 +62,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -140,10 +140,10 @@ def __init__( ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -152,7 +152,9 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -160,70 +162,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) - else: - ssl_credentials = SslCredentials().ssl_credentials - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -231,17 +213,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/base.py b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/base.py index f1a66243..4adbb0d1 100644 --- a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/base.py +++ b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/base.py @@ -69,10 +69,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -80,6 +80,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -89,20 +92,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py index f7eea171..8ae306d9 100644 --- a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py +++ b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py @@ -106,7 +106,9 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -114,70 +116,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) - else: - ssl_credentials = SslCredentials().ssl_credentials - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -185,17 +167,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -209,7 +182,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py index 80327fd8..115e2446 100644 --- a/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py +++ b/google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py @@ -61,7 +61,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -139,10 +139,10 @@ def __init__( ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -151,7 +151,9 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -159,70 +161,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) - else: - ssl_credentials = SslCredentials().ssl_credentials - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -230,17 +212,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/errorreporting_v1beta1/types/__init__.py b/google/cloud/errorreporting_v1beta1/types/__init__.py index 8819a78f..9cf5a255 100644 --- a/google/cloud/errorreporting_v1beta1/types/__init__.py +++ b/google/cloud/errorreporting_v1beta1/types/__init__.py @@ -16,13 +16,13 @@ # from .common import ( - ErrorGroup, - TrackingIssue, - ErrorEvent, - ServiceContext, ErrorContext, + ErrorEvent, + ErrorGroup, HttpRequestContext, + ServiceContext, SourceLocation, + TrackingIssue, ResolutionStatus, ) from .error_group_service import ( @@ -30,49 +30,49 @@ UpdateGroupRequest, ) from .error_stats_service import ( - ListGroupStatsRequest, - ListGroupStatsResponse, + DeleteEventsRequest, + DeleteEventsResponse, ErrorGroupStats, - TimedCount, ListEventsRequest, ListEventsResponse, + ListGroupStatsRequest, + ListGroupStatsResponse, QueryTimeRange, ServiceContextFilter, - DeleteEventsRequest, - DeleteEventsResponse, - TimedCountAlignment, + TimedCount, ErrorGroupOrder, + TimedCountAlignment, ) from .report_errors_service import ( + ReportedErrorEvent, ReportErrorEventRequest, ReportErrorEventResponse, - ReportedErrorEvent, ) __all__ = ( - "ErrorGroup", - "TrackingIssue", - "ErrorEvent", - "ServiceContext", "ErrorContext", + "ErrorEvent", + "ErrorGroup", "HttpRequestContext", + "ServiceContext", "SourceLocation", + "TrackingIssue", "ResolutionStatus", "GetGroupRequest", "UpdateGroupRequest", - "ListGroupStatsRequest", - "ListGroupStatsResponse", + "DeleteEventsRequest", + "DeleteEventsResponse", "ErrorGroupStats", - "TimedCount", "ListEventsRequest", "ListEventsResponse", + "ListGroupStatsRequest", + "ListGroupStatsResponse", "QueryTimeRange", "ServiceContextFilter", - "DeleteEventsRequest", - "DeleteEventsResponse", - "TimedCountAlignment", + "TimedCount", "ErrorGroupOrder", + "TimedCountAlignment", + "ReportedErrorEvent", "ReportErrorEventRequest", "ReportErrorEventResponse", - "ReportedErrorEvent", ) diff --git a/noxfile.py b/noxfile.py index 4e86e3af..b3e7d21e 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,6 +18,7 @@ from __future__ import absolute_import import os +import pathlib import shutil import nox @@ -30,6 +31,8 @@ SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() + # 'docfx' is excluded since it only needs to run in 'docs-presubmit' nox.options.sessions = [ "unit", @@ -41,6 +44,9 @@ "docs", ] +# Error if a python version is missing +nox.options.error_on_missing_interpreters = True + @nox.session(python=DEFAULT_PYTHON_VERSION) def lint(session): @@ -81,13 +87,15 @@ def lint_setup_py(session): def default(session): # Install all test dependencies, then install this package in-place. - session.install("asyncmock", "pytest-asyncio") - session.install( - "mock", "pytest", "pytest-cov", + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" ) + session.install("asyncmock", "pytest-asyncio", "-c", constraints_path) - session.install("-e", ".") + session.install("mock", "pytest", "pytest-cov", "-c", constraints_path) + + session.install("-e", ".", "-c", constraints_path) # Run py.test against the unit tests. session.run( @@ -114,6 +122,9 @@ def unit(session): @nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) def system(session): """Run the system test suite.""" + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" + ) system_test_path = os.path.join("tests", "system.py") system_test_folder_path = os.path.join("tests", "system") @@ -138,12 +149,10 @@ def system(session): # Install all test dependencies, then install this package into the # virtualenv's dist-packages. - session.install( - "mock", "pytest", "google-cloud-testutils", - ) - session.install("-e", "test_utils") + session.install("mock", "pytest", "google-cloud-testutils", "-c", constraints_path) + session.install("-e", "test_utils", "-c", constraints_path) - session.install("-e", ".") + session.install("-e", ".", "-c", constraints_path) # Run py.test against the system tests. if system_test_exists: @@ -172,7 +181,7 @@ def cover(session): test runs (not system test runs), and then erases coverage data. """ session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=100") + session.run("coverage", "report", "--show-missing", "--fail-under=98") session.run("coverage", "erase") @@ -204,9 +213,9 @@ def docfx(session): """Build the docfx yaml files for this library.""" session.install("-e", ".") - # sphinx-docfx-yaml supports up to sphinx version 1.5.5. - # https://github.com/docascode/sphinx-docfx-yaml/issues/97 - session.install("sphinx==1.5.5", "alabaster", "recommonmark", "sphinx-docfx-yaml") + session.install( + "sphinx<3.0.0", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml" + ) shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( diff --git a/renovate.json b/renovate.json index 4fa94931..f08bc22c 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,6 @@ { "extends": [ "config:base", ":preserveSemverRanges" - ] + ], + "ignorePaths": [".pre-commit-config.yaml"] } diff --git a/setup.py b/setup.py index d40cc0d7..e466c8f8 100644 --- a/setup.py +++ b/setup.py @@ -30,9 +30,8 @@ release_status = "Development Status :: 4 - Beta" dependencies = [ "google-cloud-logging>=1.14.0, <2.4", - "google-api-core[grpc] >= 1.22.0, < 2.0.0dev", + "google-api-core[grpc] >= 1.22.2, < 2.0.0dev", "proto-plus >= 1.4.0", - "libcst >= 0.2.5", ] extras = {} diff --git a/synth.metadata b/synth.metadata index adab2bda..d79c2e55 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,30 +3,30 @@ { "git": { "name": ".", - "remote": "https://github.com/googleapis/python-error-reporting.git", - "sha": "511be86d97804b6ae4bee0718dde5fde21bddb49" + "remote": "git@github.com:googleapis/python-error-reporting.git", + "sha": "4a5e0546148797dd7e576d21a61fd5a051488dbf" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "f6dd7e47620566925a4b3f1ce029e74e1b2f2516", - "internalRef": "359781040" + "sha": "915925089600094e72e4bfa8cf586c170e6b7109", + "internalRef": "366152684" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "0780323da96d5a53925fe0547757181fe76e8f1e" + "sha": "6d76df2138f8f841e5a5b9ac427f81def520c15f" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "0780323da96d5a53925fe0547757181fe76e8f1e" + "sha": "6d76df2138f8f841e5a5b9ac427f81def520c15f" } } ], @@ -40,122 +40,5 @@ "generator": "bazel" } } - ], - "generatedFiles": [ - ".coveragerc", - ".flake8", - ".github/CONTRIBUTING.md", - ".github/ISSUE_TEMPLATE/bug_report.md", - ".github/ISSUE_TEMPLATE/feature_request.md", - ".github/ISSUE_TEMPLATE/support_request.md", - ".github/PULL_REQUEST_TEMPLATE.md", - ".github/header-checker-lint.yml", - ".github/release-please.yml", - ".github/snippet-bot.yml", - ".gitignore", - ".kokoro/build.sh", - ".kokoro/continuous/common.cfg", - ".kokoro/continuous/continuous.cfg", - ".kokoro/docker/docs/Dockerfile", - ".kokoro/docker/docs/fetch_gpg_keys.sh", - ".kokoro/docs/common.cfg", - ".kokoro/docs/docs-presubmit.cfg", - ".kokoro/docs/docs.cfg", - ".kokoro/populate-secrets.sh", - ".kokoro/presubmit/common.cfg", - ".kokoro/presubmit/presubmit.cfg", - ".kokoro/publish-docs.sh", - ".kokoro/release.sh", - ".kokoro/release/common.cfg", - ".kokoro/release/release.cfg", - ".kokoro/samples/lint/common.cfg", - ".kokoro/samples/lint/continuous.cfg", - ".kokoro/samples/lint/periodic.cfg", - ".kokoro/samples/lint/presubmit.cfg", - ".kokoro/samples/python3.6/common.cfg", - ".kokoro/samples/python3.6/continuous.cfg", - ".kokoro/samples/python3.6/periodic.cfg", - ".kokoro/samples/python3.6/presubmit.cfg", - ".kokoro/samples/python3.7/common.cfg", - ".kokoro/samples/python3.7/continuous.cfg", - ".kokoro/samples/python3.7/periodic.cfg", - ".kokoro/samples/python3.7/presubmit.cfg", - ".kokoro/samples/python3.8/common.cfg", - ".kokoro/samples/python3.8/continuous.cfg", - ".kokoro/samples/python3.8/periodic.cfg", - ".kokoro/samples/python3.8/presubmit.cfg", - ".kokoro/test-samples.sh", - ".kokoro/trampoline.sh", - ".kokoro/trampoline_v2.sh", - ".pre-commit-config.yaml", - ".trampolinerc", - "CODE_OF_CONDUCT.md", - "CONTRIBUTING.rst", - "LICENSE", - "MANIFEST.in", - "docs/_static/custom.css", - "docs/_templates/layout.html", - "docs/conf.py", - "docs/errorreporting_v1beta1/error_group_service.rst", - "docs/errorreporting_v1beta1/error_stats_service.rst", - "docs/errorreporting_v1beta1/report_errors_service.rst", - "docs/errorreporting_v1beta1/services.rst", - "docs/errorreporting_v1beta1/types.rst", - "docs/multiprocessing.rst", - "google/cloud/errorreporting_v1beta1/__init__.py", - "google/cloud/errorreporting_v1beta1/proto/common.proto", - "google/cloud/errorreporting_v1beta1/proto/error_group_service.proto", - "google/cloud/errorreporting_v1beta1/proto/error_stats_service.proto", - "google/cloud/errorreporting_v1beta1/proto/report_errors_service.proto", - "google/cloud/errorreporting_v1beta1/py.typed", - "google/cloud/errorreporting_v1beta1/services/__init__.py", - "google/cloud/errorreporting_v1beta1/services/error_group_service/__init__.py", - "google/cloud/errorreporting_v1beta1/services/error_group_service/async_client.py", - "google/cloud/errorreporting_v1beta1/services/error_group_service/client.py", - "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/__init__.py", - "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/base.py", - "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py", - "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/__init__.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/async_client.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/client.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/pagers.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/__init__.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/base.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py", - "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py", - "google/cloud/errorreporting_v1beta1/services/report_errors_service/__init__.py", - "google/cloud/errorreporting_v1beta1/services/report_errors_service/async_client.py", - "google/cloud/errorreporting_v1beta1/services/report_errors_service/client.py", - "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/__init__.py", - "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/base.py", - "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py", - "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py", - "google/cloud/errorreporting_v1beta1/types/__init__.py", - "google/cloud/errorreporting_v1beta1/types/common.py", - "google/cloud/errorreporting_v1beta1/types/error_group_service.py", - "google/cloud/errorreporting_v1beta1/types/error_stats_service.py", - "google/cloud/errorreporting_v1beta1/types/report_errors_service.py", - "mypy.ini", - "noxfile.py", - "renovate.json", - "samples/AUTHORING_GUIDE.md", - "samples/CONTRIBUTING.md", - "samples/snippets/api/noxfile.py", - "samples/snippets/fluent_on_compute/noxfile.py", - "scripts/decrypt-secrets.sh", - "scripts/fixup_errorreporting_v1beta1_keywords.py", - "scripts/readme-gen/readme_gen.py", - "scripts/readme-gen/templates/README.tmpl.rst", - "scripts/readme-gen/templates/auth.tmpl.rst", - "scripts/readme-gen/templates/auth_api_key.tmpl.rst", - "scripts/readme-gen/templates/install_deps.tmpl.rst", - "scripts/readme-gen/templates/install_portaudio.tmpl.rst", - "setup.cfg", - "testing/.gitignore", - "tests/unit/gapic/errorreporting_v1beta1/__init__.py", - "tests/unit/gapic/errorreporting_v1beta1/test_error_group_service.py", - "tests/unit/gapic/errorreporting_v1beta1/test_error_stats_service.py", - "tests/unit/gapic/errorreporting_v1beta1/test_report_errors_service.py" ] } \ No newline at end of file diff --git a/synth.py b/synth.py index 46a9fe17..5fb57f34 100644 --- a/synth.py +++ b/synth.py @@ -37,7 +37,8 @@ templated_files = common.py_library( samples=True, # set to True only if there are samples microgenerator=True, - system_test_dependencies=["test_utils"] + system_test_dependencies=["test_utils"], + cov_level=98, ) s.move(templated_files, excludes=[".coveragerc"]) # microgenerator has a good .coveragerc file @@ -46,8 +47,5 @@ # ---------------------------------------------------------------------------- python.py_samples(skip_readmes=True) -# TODO(busunkim): Use latest sphinx after microgenerator transition -s.replace("noxfile.py", """['"]sphinx['"]""", '"sphinx<3.0.0"') - s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index e88377ad..cf04f5fa 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -6,6 +6,5 @@ # e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev", # Then this file should have foo==1.14.0 google-cloud-logging==1.14.0 -google-api-core==1.22.0 +google-api-core==1.22.2 proto-plus==1.4.0 -libcst==0.2.5 \ No newline at end of file From 86c5c543d2b278c5b93ea26d42ab3e57281dd4f0 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 1 Apr 2021 16:36:54 -0700 Subject: [PATCH 11/13] chore: release 1.1.2 (#98) Release-As: 1.1.2 From a118123cbfe8b5dd2a7ba260631b248c351cb116 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 5 Apr 2021 10:50:40 -0700 Subject: [PATCH 12/13] deps: upgrade sphinx (#99) --- .../cloud/errorreporting_v1beta1/__init__.py | 4 +- noxfile.py | 6 +- synth.metadata | 126 +++++++++++++++++- 3 files changed, 128 insertions(+), 8 deletions(-) diff --git a/google/cloud/errorreporting_v1beta1/__init__.py b/google/cloud/errorreporting_v1beta1/__init__.py index 8ced2656..56f82962 100644 --- a/google/cloud/errorreporting_v1beta1/__init__.py +++ b/google/cloud/errorreporting_v1beta1/__init__.py @@ -52,7 +52,6 @@ "ErrorEvent", "ErrorGroup", "ErrorGroupOrder", - "ErrorGroupServiceClient", "ErrorGroupStats", "ErrorStatsServiceClient", "GetGroupRequest", @@ -64,6 +63,7 @@ "QueryTimeRange", "ReportErrorEventRequest", "ReportErrorEventResponse", + "ReportErrorsServiceClient", "ReportedErrorEvent", "ResolutionStatus", "ServiceContext", @@ -73,5 +73,5 @@ "TimedCountAlignment", "TrackingIssue", "UpdateGroupRequest", - "ReportErrorsServiceClient", + "ErrorGroupServiceClient", ) diff --git a/noxfile.py b/noxfile.py index b3e7d21e..3f66499f 100644 --- a/noxfile.py +++ b/noxfile.py @@ -191,7 +191,7 @@ def docs(session): """Build the docs for this library.""" session.install("-e", ".") - session.install("sphinx<3.0.0", "alabaster", "recommonmark") + session.install("sphinx", "alabaster", "recommonmark") shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( @@ -213,9 +213,7 @@ def docfx(session): """Build the docfx yaml files for this library.""" session.install("-e", ".") - session.install( - "sphinx<3.0.0", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml" - ) + session.install("sphinx", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml") shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( diff --git a/synth.metadata b/synth.metadata index d79c2e55..bba4a1eb 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,8 +3,8 @@ { "git": { "name": ".", - "remote": "git@github.com:googleapis/python-error-reporting.git", - "sha": "4a5e0546148797dd7e576d21a61fd5a051488dbf" + "remote": "https://github.com/googleapis/python-error-reporting.git", + "sha": "86c5c543d2b278c5b93ea26d42ab3e57281dd4f0" } }, { @@ -40,5 +40,127 @@ "generator": "bazel" } } + ], + "generatedFiles": [ + ".coveragerc", + ".flake8", + ".github/CONTRIBUTING.md", + ".github/ISSUE_TEMPLATE/bug_report.md", + ".github/ISSUE_TEMPLATE/feature_request.md", + ".github/ISSUE_TEMPLATE/support_request.md", + ".github/PULL_REQUEST_TEMPLATE.md", + ".github/header-checker-lint.yml", + ".github/release-please.yml", + ".github/snippet-bot.yml", + ".gitignore", + ".kokoro/build.sh", + ".kokoro/continuous/common.cfg", + ".kokoro/continuous/continuous.cfg", + ".kokoro/docker/docs/Dockerfile", + ".kokoro/docker/docs/fetch_gpg_keys.sh", + ".kokoro/docs/common.cfg", + ".kokoro/docs/docs-presubmit.cfg", + ".kokoro/docs/docs.cfg", + ".kokoro/populate-secrets.sh", + ".kokoro/presubmit/common.cfg", + ".kokoro/presubmit/presubmit.cfg", + ".kokoro/publish-docs.sh", + ".kokoro/release.sh", + ".kokoro/release/common.cfg", + ".kokoro/release/release.cfg", + ".kokoro/samples/lint/common.cfg", + ".kokoro/samples/lint/continuous.cfg", + ".kokoro/samples/lint/periodic.cfg", + ".kokoro/samples/lint/presubmit.cfg", + ".kokoro/samples/python3.6/common.cfg", + ".kokoro/samples/python3.6/continuous.cfg", + ".kokoro/samples/python3.6/periodic-head.cfg", + ".kokoro/samples/python3.6/periodic.cfg", + ".kokoro/samples/python3.6/presubmit.cfg", + ".kokoro/samples/python3.7/common.cfg", + ".kokoro/samples/python3.7/continuous.cfg", + ".kokoro/samples/python3.7/periodic-head.cfg", + ".kokoro/samples/python3.7/periodic.cfg", + ".kokoro/samples/python3.7/presubmit.cfg", + ".kokoro/samples/python3.8/common.cfg", + ".kokoro/samples/python3.8/continuous.cfg", + ".kokoro/samples/python3.8/periodic-head.cfg", + ".kokoro/samples/python3.8/periodic.cfg", + ".kokoro/samples/python3.8/presubmit.cfg", + ".kokoro/test-samples-against-head.sh", + ".kokoro/test-samples-impl.sh", + ".kokoro/test-samples.sh", + ".kokoro/trampoline.sh", + ".kokoro/trampoline_v2.sh", + ".pre-commit-config.yaml", + ".trampolinerc", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.rst", + "LICENSE", + "MANIFEST.in", + "docs/_static/custom.css", + "docs/_templates/layout.html", + "docs/conf.py", + "docs/errorreporting_v1beta1/error_group_service.rst", + "docs/errorreporting_v1beta1/error_stats_service.rst", + "docs/errorreporting_v1beta1/report_errors_service.rst", + "docs/errorreporting_v1beta1/services.rst", + "docs/errorreporting_v1beta1/types.rst", + "docs/multiprocessing.rst", + "google/cloud/errorreporting_v1beta1/__init__.py", + "google/cloud/errorreporting_v1beta1/proto/common.proto", + "google/cloud/errorreporting_v1beta1/proto/error_group_service.proto", + "google/cloud/errorreporting_v1beta1/proto/error_stats_service.proto", + "google/cloud/errorreporting_v1beta1/proto/report_errors_service.proto", + "google/cloud/errorreporting_v1beta1/py.typed", + "google/cloud/errorreporting_v1beta1/services/__init__.py", + "google/cloud/errorreporting_v1beta1/services/error_group_service/__init__.py", + "google/cloud/errorreporting_v1beta1/services/error_group_service/async_client.py", + "google/cloud/errorreporting_v1beta1/services/error_group_service/client.py", + "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/__init__.py", + "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/base.py", + "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc.py", + "google/cloud/errorreporting_v1beta1/services/error_group_service/transports/grpc_asyncio.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/__init__.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/async_client.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/client.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/pagers.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/__init__.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/base.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc.py", + "google/cloud/errorreporting_v1beta1/services/error_stats_service/transports/grpc_asyncio.py", + "google/cloud/errorreporting_v1beta1/services/report_errors_service/__init__.py", + "google/cloud/errorreporting_v1beta1/services/report_errors_service/async_client.py", + "google/cloud/errorreporting_v1beta1/services/report_errors_service/client.py", + "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/__init__.py", + "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/base.py", + "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc.py", + "google/cloud/errorreporting_v1beta1/services/report_errors_service/transports/grpc_asyncio.py", + "google/cloud/errorreporting_v1beta1/types/__init__.py", + "google/cloud/errorreporting_v1beta1/types/common.py", + "google/cloud/errorreporting_v1beta1/types/error_group_service.py", + "google/cloud/errorreporting_v1beta1/types/error_stats_service.py", + "google/cloud/errorreporting_v1beta1/types/report_errors_service.py", + "mypy.ini", + "noxfile.py", + "renovate.json", + "samples/AUTHORING_GUIDE.md", + "samples/CONTRIBUTING.md", + "samples/snippets/api/noxfile.py", + "samples/snippets/fluent_on_compute/noxfile.py", + "scripts/decrypt-secrets.sh", + "scripts/fixup_errorreporting_v1beta1_keywords.py", + "scripts/readme-gen/readme_gen.py", + "scripts/readme-gen/templates/README.tmpl.rst", + "scripts/readme-gen/templates/auth.tmpl.rst", + "scripts/readme-gen/templates/auth_api_key.tmpl.rst", + "scripts/readme-gen/templates/install_deps.tmpl.rst", + "scripts/readme-gen/templates/install_portaudio.tmpl.rst", + "setup.cfg", + "testing/.gitignore", + "tests/unit/gapic/errorreporting_v1beta1/__init__.py", + "tests/unit/gapic/errorreporting_v1beta1/test_error_group_service.py", + "tests/unit/gapic/errorreporting_v1beta1/test_error_stats_service.py", + "tests/unit/gapic/errorreporting_v1beta1/test_report_errors_service.py" ] } \ No newline at end of file From 0e13cca302a6ccd80e36ab0a79869301a51a75f6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 5 Apr 2021 10:57:48 -0700 Subject: [PATCH 13/13] chore: release 1.1.2 (#100) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 7 +++++++ setup.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb91480..3e874fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ [1]: https://pypi.org/project/google-cloud-error-reporting/#history +### [1.1.2](https://www.github.com/googleapis/python-error-reporting/compare/v1.1.1...v1.1.2) (2021-04-05) + + +### Dependencies + +* upgrade sphinx ([#99](https://www.github.com/googleapis/python-error-reporting/issues/99)) ([a118123](https://www.github.com/googleapis/python-error-reporting/commit/a118123cbfe8b5dd2a7ba260631b248c351cb116)) + ### [1.1.1](https://www.github.com/googleapis/python-error-reporting/compare/v1.1.0...v1.1.1) (2021-02-25) diff --git a/setup.py b/setup.py index e466c8f8..859ef21d 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ name = "google-cloud-error-reporting" description = "Error Reporting API client library" -version = "1.1.1" +version = "1.1.2" # Should be one of: # 'Development Status :: 3 - Alpha' # 'Development Status :: 4 - Beta'