diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml new file mode 100644 index 0000000..4ef4414 --- /dev/null +++ b/.github/.OwlBot.lock.yaml @@ -0,0 +1,3 @@ +docker: + image: gcr.io/repo-automation-bots/owlbot-python:latest + digest: sha256:c66ba3c8d7bc8566f47df841f98cd0097b28fff0b1864c86f5817f4c8c3e8600 \ No newline at end of file diff --git a/.github/.OwlBot.yaml b/.github/.OwlBot.yaml new file mode 100644 index 0000000..8cab089 --- /dev/null +++ b/.github/.OwlBot.yaml @@ -0,0 +1,26 @@ +# 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 +# +# 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. + +docker: + image: gcr.io/repo-automation-bots/owlbot-python:latest + +deep-remove-regex: + - /owl-bot-staging + +deep-copy-regex: + - source: /google/cloud/webrisk/(v.*)/.*-py/(.*) + dest: /owl-bot-staging/$1/$2 + +begin-after-commit-hash: 70f7f0525414fe4dfeb2fc2e81546b073f83a621 + diff --git a/.github/header-checker-lint.yml b/.github/header-checker-lint.yml index fc281c0..6fe78aa 100644 --- a/.github/header-checker-lint.yml +++ b/.github/header-checker-lint.yml @@ -1,6 +1,6 @@ {"allowedCopyrightHolders": ["Google LLC"], "allowedLicenses": ["Apache-2.0", "MIT", "BSD-3"], - "ignoreFiles": ["**/requirements.txt", "**/requirements-test.txt"], + "ignoreFiles": ["**/requirements.txt", "**/requirements-test.txt", "**/__init__.py", "samples/**/constraints.txt", "samples/**/constraints-test.txt"], "sourceFileExtensions": [ "ts", "js", diff --git a/.kokoro/release.sh b/.kokoro/release.sh index 698b035..5d00ace 100755 --- a/.kokoro/release.sh +++ b/.kokoro/release.sh @@ -26,7 +26,7 @@ python3 -m pip install --upgrade twine wheel setuptools export PYTHONUNBUFFERED=1 # Move into the package, build the distribution and upload. -TWINE_PASSWORD=$(cat "${KOKORO_KEYSTORE_DIR}/73713_google_cloud_pypi_password") +TWINE_PASSWORD=$(cat "${KOKORO_GFILE_DIR}/secret_manager/google-cloud-pypi-token") cd github/python-webrisk python3 setup.py sdist bdist_wheel -twine upload --username gcloudpypi --password "${TWINE_PASSWORD}" dist/* +twine upload --username __token__ --password "${TWINE_PASSWORD}" dist/* diff --git a/.kokoro/release/common.cfg b/.kokoro/release/common.cfg index 4de893c..2bb8de1 100644 --- a/.kokoro/release/common.cfg +++ b/.kokoro/release/common.cfg @@ -23,18 +23,8 @@ env_vars: { value: "github/python-webrisk/.kokoro/release.sh" } -# Fetch PyPI password -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "google_cloud_pypi_password" - } - } -} - # Tokens needed to report release status back to GitHub env_vars: { key: "SECRET_MANAGER_KEYS" - value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" -} \ No newline at end of file + value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem,google-cloud-pypi-token" +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 32302e4..4f00c7c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,17 @@ +# 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 +# +# 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. +# # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: @@ -12,6 +26,6 @@ repos: hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.0 + rev: 3.9.2 hooks: - id: flake8 diff --git a/.repo-metadata.json b/.repo-metadata.json index 363ab44..3304493 100644 --- a/.repo-metadata.json +++ b/.repo-metadata.json @@ -4,8 +4,9 @@ "product_documentation": "https://cloud.google.com/web-risk/docs/", "client_documentation": "https://googleapis.dev/python/webrisk/latest", "issue_tracker": "", - "release_level": "alpha", + "release_level": "ga", "language": "python", + "library_type": "GAPIC_AUTO", "repo": "googleapis/python-webrisk", "distribution_name": "google-cloud-webrisk", "api_id": "webrisk.googleapis.com", diff --git a/CHANGELOG.md b/CHANGELOG.md index 705ea63..34d39fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ [PyPI History][1] [1]: https://pypi.org/project/google-cloud-webrisk/#history +## [1.3.0](https://www.github.com/googleapis/python-webrisk/compare/v1.2.0...v1.3.0) (2021-06-01) + + +### Features + +* bump release level to production/stable ([#81](https://www.github.com/googleapis/python-webrisk/issues/81)) ([0946b75](https://www.github.com/googleapis/python-webrisk/commit/0946b753e9371a4f275035cf35b11fd6b5b5464e)), closes [#20](https://www.github.com/googleapis/python-webrisk/issues/20) + + +### Bug Fixes + +* **deps:** add packaging requirement ([#82](https://www.github.com/googleapis/python-webrisk/issues/82)) ([4ec0245](https://www.github.com/googleapis/python-webrisk/commit/4ec0245957d14816bd3ed293e617f5cf830850f4)) + ## [1.2.0](https://www.github.com/googleapis/python-webrisk/compare/v1.1.0...v1.2.0) (2021-03-31) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 782c0d2..6682ead 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -160,21 +160,7 @@ Running System Tests auth settings and change some configuration in your project to run all the tests. -- System tests will be run against an actual project and - so you'll need to provide some environment variables to facilitate - authentication to your project: - - - ``GOOGLE_APPLICATION_CREDENTIALS``: The path to a JSON key file; - Such a file can be downloaded directly from the developer's console by clicking - "Generate new JSON key". See private key - `docs `__ - for more details. - -- Once you have downloaded your json keys, set the environment variable - ``GOOGLE_APPLICATION_CREDENTIALS`` to the absolute path of the json file:: - - $ export GOOGLE_APPLICATION_CREDENTIALS="/Users//path/to/app_credentials.json" - +- System tests will be run against an actual project. You should use local credentials from gcloud when possible. See `Best practices for application authentication `__. Some tests require a service account. For those tests see `Authenticating as a service account `__. ************* Test Coverage diff --git a/README.rst b/README.rst index 51ed765..0e2fef5 100644 --- a/README.rst +++ b/README.rst @@ -1,19 +1,20 @@ -Python Client for Web Risk API (`Alpha`_) -========================================= +Python Client for Web Risk API +============================== +|ga| |pypi| |versions| - -**Note:** Cloud Web Risk is not yet publicly available. You must be whitelisted in order to gain access. See `Setting up the Web Risk API`_ in the product documentation for a link to the sign-up form. - -.. _Setting up the Web Risk API: - -`Web Risk API`: https://cloud.google.com/web-risk/docs/quickstart +.. _Setting up Web Risk: https://cloud.google.com/web-risk/docs/quickstart - `Client Library Documentation`_ - `Product Documentation`_ -.. _Alpha: https://github.com/googleapis/google-cloud-python/blob/master/README.rst -.. _Web Risk API: https://cloud.google.com/web-risk +.. |ga| image:: https://img.shields.io/badge/support-ga-gold.svg + :target: https://github.com/googleapis/google-cloud-python/blob/master/README.rst#ga-support +.. |pypi| image:: https://img.shields.io/pypi/v/google-cloud-webrisk.svg + :target: https://pypi.org/project/google-cloud-webrisk/ +.. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-webrisk.svg + :target: https://pypi.org/project/google-cloud-webrisk/ + .. _Client Library Documentation: https://googleapis.dev/python/webrisk/latest .. _Product Documentation: https://cloud.google.com/web-risk diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..8b58ae9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). + +The Google Security Team will respond within 5 working days of your report on g.co/vulnz. + +We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. diff --git a/docs/_static/custom.css b/docs/_static/custom.css index bcd37bb..b0a2954 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -1,9 +1,20 @@ div#python2-eol { border-color: red; border-width: medium; -} +} /* Ensure minimum width for 'Parameters' / 'Returns' column */ dl.field-list > dt { min-width: 100px } + +/* Insert space between methods for readability */ +dl.method { + padding-top: 10px; + padding-bottom: 10px +} + +/* Insert empty space between classes */ +dl.class { + padding-bottom: 50px +} diff --git a/docs/conf.py b/docs/conf.py index 327c455..cd4b9c2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,17 @@ # -*- coding: utf-8 -*- +# 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 +# +# 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. # # google-cloud-webrisk documentation build configuration file # @@ -350,6 +363,7 @@ "google.api_core": ("https://googleapis.dev/python/google-api-core/latest/", None,), "grpc": ("https://grpc.github.io/grpc/python/", None), "proto-plus": ("https://proto-plus-python.readthedocs.io/en/latest/", None), + "protobuf": ("https://googleapis.dev/python/protobuf/latest/", None), } diff --git a/docs/multiprocessing.rst b/docs/multiprocessing.rst index 1cb29d4..536d17b 100644 --- a/docs/multiprocessing.rst +++ b/docs/multiprocessing.rst @@ -1,7 +1,7 @@ .. note:: - Because this client uses :mod:`grpcio` library, it is safe to + Because this client uses :mod:`grpc` library, it is safe to share instances across threads. In multiprocessing scenarios, the best practice is to create client instances *after* the invocation of - :func:`os.fork` by :class:`multiprocessing.Pool` or + :func:`os.fork` by :class:`multiprocessing.pool.Pool` or :class:`multiprocessing.Process`. diff --git a/google/cloud/webrisk/__init__.py b/google/cloud/webrisk/__init__.py index d78ab4c..15ccb36 100644 --- a/google/cloud/webrisk/__init__.py +++ b/google/cloud/webrisk/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,13 +14,13 @@ # limitations under the License. # -from google.cloud.webrisk_v1.services.web_risk_service.async_client import ( - WebRiskServiceAsyncClient, -) from google.cloud.webrisk_v1.services.web_risk_service.client import ( WebRiskServiceClient, ) -from google.cloud.webrisk_v1.types.webrisk import CompressionType +from google.cloud.webrisk_v1.services.web_risk_service.async_client import ( + WebRiskServiceAsyncClient, +) + from google.cloud.webrisk_v1.types.webrisk import ComputeThreatListDiffRequest from google.cloud.webrisk_v1.types.webrisk import ComputeThreatListDiffResponse from google.cloud.webrisk_v1.types.webrisk import CreateSubmissionRequest @@ -35,10 +34,12 @@ from google.cloud.webrisk_v1.types.webrisk import Submission from google.cloud.webrisk_v1.types.webrisk import ThreatEntryAdditions from google.cloud.webrisk_v1.types.webrisk import ThreatEntryRemovals +from google.cloud.webrisk_v1.types.webrisk import CompressionType from google.cloud.webrisk_v1.types.webrisk import ThreatType __all__ = ( - "CompressionType", + "WebRiskServiceClient", + "WebRiskServiceAsyncClient", "ComputeThreatListDiffRequest", "ComputeThreatListDiffResponse", "CreateSubmissionRequest", @@ -52,7 +53,6 @@ "Submission", "ThreatEntryAdditions", "ThreatEntryRemovals", + "CompressionType", "ThreatType", - "WebRiskServiceAsyncClient", - "WebRiskServiceClient", ) diff --git a/google/cloud/webrisk_v1/__init__.py b/google/cloud/webrisk_v1/__init__.py index 5ba2bcd..59bfad9 100644 --- a/google/cloud/webrisk_v1/__init__.py +++ b/google/cloud/webrisk_v1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +15,8 @@ # from .services.web_risk_service import WebRiskServiceClient -from .types.webrisk import CompressionType +from .services.web_risk_service import WebRiskServiceAsyncClient + from .types.webrisk import ComputeThreatListDiffRequest from .types.webrisk import ComputeThreatListDiffResponse from .types.webrisk import CreateSubmissionRequest @@ -30,10 +30,11 @@ from .types.webrisk import Submission from .types.webrisk import ThreatEntryAdditions from .types.webrisk import ThreatEntryRemovals +from .types.webrisk import CompressionType from .types.webrisk import ThreatType - __all__ = ( + "WebRiskServiceAsyncClient", "CompressionType", "ComputeThreatListDiffRequest", "ComputeThreatListDiffResponse", diff --git a/google/cloud/webrisk_v1/gapic_metadata.json b/google/cloud/webrisk_v1/gapic_metadata.json new file mode 100644 index 0000000..fc56236 --- /dev/null +++ b/google/cloud/webrisk_v1/gapic_metadata.json @@ -0,0 +1,63 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.webrisk_v1", + "protoPackage": "google.cloud.webrisk.v1", + "schema": "1.0", + "services": { + "WebRiskService": { + "clients": { + "grpc": { + "libraryClient": "WebRiskServiceClient", + "rpcs": { + "ComputeThreatListDiff": { + "methods": [ + "compute_threat_list_diff" + ] + }, + "CreateSubmission": { + "methods": [ + "create_submission" + ] + }, + "SearchHashes": { + "methods": [ + "search_hashes" + ] + }, + "SearchUris": { + "methods": [ + "search_uris" + ] + } + } + }, + "grpc-async": { + "libraryClient": "WebRiskServiceAsyncClient", + "rpcs": { + "ComputeThreatListDiff": { + "methods": [ + "compute_threat_list_diff" + ] + }, + "CreateSubmission": { + "methods": [ + "create_submission" + ] + }, + "SearchHashes": { + "methods": [ + "search_hashes" + ] + }, + "SearchUris": { + "methods": [ + "search_uris" + ] + } + } + } + } + } + } +} diff --git a/google/cloud/webrisk_v1/proto/webrisk.proto b/google/cloud/webrisk_v1/proto/webrisk.proto deleted file mode 100644 index 71b6b44..0000000 --- a/google/cloud/webrisk_v1/proto/webrisk.proto +++ /dev/null @@ -1,353 +0,0 @@ -// 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. - -syntax = "proto3"; - -package google.cloud.webrisk.v1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/api/resource.proto"; -import "google/protobuf/timestamp.proto"; - -option csharp_namespace = "Google.Cloud.WebRisk.V1"; -option go_package = "google.golang.org/genproto/googleapis/cloud/webrisk/v1;webrisk"; -option java_multiple_files = true; -option java_outer_classname = "WebRiskProto"; -option java_package = "com.google.webrisk.v1"; -option objc_class_prefix = "GCWR"; -option php_namespace = "Google\\Cloud\\WebRisk\\V1"; -option ruby_package = "Google::Cloud::WebRisk::V1"; - -// Web Risk API defines an interface to detect malicious URLs on your -// website and in client applications. -service WebRiskService { - option (google.api.default_host) = "webrisk.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Gets the most recent threat list diffs. These diffs should be applied to - // a local database of hashes to keep it up-to-date. If the local database is - // empty or excessively out-of-date, a complete snapshot of the database will - // be returned. This Method only updates a single ThreatList at a time. To - // update multiple ThreatList databases, this method needs to be called once - // for each list. - rpc ComputeThreatListDiff(ComputeThreatListDiffRequest) returns (ComputeThreatListDiffResponse) { - option (google.api.http) = { - get: "/v1/threatLists:computeDiff" - }; - option (google.api.method_signature) = "threat_type,version_token,constraints"; - } - - // This method is used to check whether a URI is on a given threatList. - // Multiple threatLists may be searched in a single query. - // The response will list all requested threatLists the URI was found to - // match. If the URI is not found on any of the requested ThreatList an - // empty response will be returned. - rpc SearchUris(SearchUrisRequest) returns (SearchUrisResponse) { - option (google.api.http) = { - get: "/v1/uris:search" - }; - option (google.api.method_signature) = "uri,threat_types"; - } - - // Gets the full hashes that match the requested hash prefix. - // This is used after a hash prefix is looked up in a threatList - // and there is a match. The client side threatList only holds partial hashes - // so the client must query this method to determine if there is a full - // hash match of a threat. - rpc SearchHashes(SearchHashesRequest) returns (SearchHashesResponse) { - option (google.api.http) = { - get: "/v1/hashes:search" - }; - option (google.api.method_signature) = "hash_prefix,threat_types"; - } - - // Creates a Submission of a URI suspected of containing phishing content to - // be reviewed. If the result verifies the existence of malicious phishing - // content, the site will be added to the [Google's Social Engineering - // lists](https://support.google.com/webmasters/answer/6350487/) in order to - // protect users that could get exposed to this threat in the future. Only - // projects with CREATE_SUBMISSION_USERS visibility can use this method. - rpc CreateSubmission(CreateSubmissionRequest) returns (Submission) { - option (google.api.http) = { - post: "/v1/{parent=projects/*}/submissions" - body: "submission" - }; - option (google.api.method_signature) = "parent,submission"; - } -} - -// Describes an API diff request. -message ComputeThreatListDiffRequest { - // The constraints for this diff. - message Constraints { - // The maximum size in number of entries. The diff will not contain more - // entries than this value. This should be a power of 2 between 2**10 and - // 2**20. If zero, no diff size limit is set. - int32 max_diff_entries = 1; - - // Sets the maximum number of entries that the client is willing to have - // in the local database. This should be a power of 2 between 2**10 and - // 2**20. If zero, no database size limit is set. - int32 max_database_entries = 2; - - // The compression types supported by the client. - repeated CompressionType supported_compressions = 3; - } - - // Required. The threat list to update. Only a single ThreatType should be specified. - ThreatType threat_type = 1 [(google.api.field_behavior) = REQUIRED]; - - // The current version token of the client for the requested list (the - // client version that was received from the last successful diff). - // If the client does not have a version token (this is the first time calling - // ComputeThreatListDiff), this may be left empty and a full database - // snapshot will be returned. - bytes version_token = 2; - - // Required. The constraints associated with this request. - Constraints constraints = 3 [(google.api.field_behavior) = REQUIRED]; -} - -message ComputeThreatListDiffResponse { - // The expected state of a client's local database. - message Checksum { - // The SHA256 hash of the client state; that is, of the sorted list of all - // hashes present in the database. - bytes sha256 = 1; - } - - // The type of response sent to the client. - enum ResponseType { - // Unknown. - RESPONSE_TYPE_UNSPECIFIED = 0; - - // Partial updates are applied to the client's existing local database. - DIFF = 1; - - // Full updates resets the client's entire local database. This means - // that either the client had no state, was seriously out-of-date, - // or the client is believed to be corrupt. - RESET = 2; - } - - // The type of response. This may indicate that an action must be taken by the - // client when the response is received. - ResponseType response_type = 4; - - // A set of entries to add to a local threat type's list. - ThreatEntryAdditions additions = 5; - - // A set of entries to remove from a local threat type's list. - // This field may be empty. - ThreatEntryRemovals removals = 6; - - // The new opaque client version token. This should be retained by the client - // and passed into the next call of ComputeThreatListDiff as 'version_token'. - // A separate version token should be stored and used for each threatList. - bytes new_version_token = 7; - - // The expected SHA256 hash of the client state; that is, of the sorted list - // of all hashes present in the database after applying the provided diff. - // If the client state doesn't match the expected state, the client must - // discard this diff and retry later. - Checksum checksum = 8; - - // The soonest the client should wait before issuing any diff - // request. Querying sooner is unlikely to produce a meaningful diff. - // Waiting longer is acceptable considering the use case. - // If this field is not set clients may update as soon as they want. - google.protobuf.Timestamp recommended_next_diff = 2; -} - -// Request to check URI entries against threatLists. -message SearchUrisRequest { - // Required. The URI to be checked for matches. - string uri = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The ThreatLists to search in. Multiple ThreatLists may be specified. - repeated ThreatType threat_types = 2 [(google.api.field_behavior) = REQUIRED]; -} - -message SearchUrisResponse { - // Contains threat information on a matching uri. - message ThreatUri { - // The ThreatList this threat belongs to. - repeated ThreatType threat_types = 1; - - // The cache lifetime for the returned match. Clients must not cache this - // response past this timestamp to avoid false positives. - google.protobuf.Timestamp expire_time = 2; - } - - // The threat list matches. This may be empty if the URI is on no list. - ThreatUri threat = 1; -} - -// Request to return full hashes matched by the provided hash prefixes. -message SearchHashesRequest { - // A hash prefix, consisting of the most significant 4-32 bytes of a SHA256 - // hash. For JSON requests, this field is base64-encoded. - bytes hash_prefix = 1; - - // Required. The ThreatLists to search in. Multiple ThreatLists may be specified. - repeated ThreatType threat_types = 2 [(google.api.field_behavior) = REQUIRED]; -} - -message SearchHashesResponse { - // Contains threat information on a matching hash. - message ThreatHash { - // The ThreatList this threat belongs to. - // This must contain at least one entry. - repeated ThreatType threat_types = 1; - - // A 32 byte SHA256 hash. This field is in binary format. For JSON - // requests, hashes are base64-encoded. - bytes hash = 2; - - // The cache lifetime for the returned match. Clients must not cache this - // response past this timestamp to avoid false positives. - google.protobuf.Timestamp expire_time = 3; - } - - // The full hashes that matched the requested prefixes. - // The hash will be populated in the key. - repeated ThreatHash threats = 1; - - // For requested entities that did not match the threat list, how long to - // cache the response until. - google.protobuf.Timestamp negative_expire_time = 2; -} - -// Contains the set of entries to add to a local database. -// May contain a combination of compressed and raw data in a single response. -message ThreatEntryAdditions { - // The raw SHA256-formatted entries. - // Repeated to allow returning sets of hashes with different prefix sizes. - repeated RawHashes raw_hashes = 1; - - // The encoded 4-byte prefixes of SHA256-formatted entries, using a - // Golomb-Rice encoding. The hashes are converted to uint32, sorted in - // ascending order, then delta encoded and stored as encoded_data. - RiceDeltaEncoding rice_hashes = 2; -} - -// Contains the set of entries to remove from a local database. -message ThreatEntryRemovals { - // The raw removal indices for a local list. - RawIndices raw_indices = 1; - - // The encoded local, lexicographically-sorted list indices, using a - // Golomb-Rice encoding. Used for sending compressed removal indices. The - // removal indices (uint32) are sorted in ascending order, then delta encoded - // and stored as encoded_data. - RiceDeltaEncoding rice_indices = 2; -} - -// The type of threat. This maps dirrectly to the threat list a threat may -// belong to. -enum ThreatType { - // Unknown. - THREAT_TYPE_UNSPECIFIED = 0; - - // Malware targeting any platform. - MALWARE = 1; - - // Social engineering targeting any platform. - SOCIAL_ENGINEERING = 2; - - // Unwanted software targeting any platform. - UNWANTED_SOFTWARE = 3; -} - -// The ways in which threat entry sets can be compressed. -enum CompressionType { - // Unknown. - COMPRESSION_TYPE_UNSPECIFIED = 0; - - // Raw, uncompressed data. - RAW = 1; - - // Rice-Golomb encoded data. - RICE = 2; -} - -// A set of raw indices to remove from a local list. -message RawIndices { - // The indices to remove from a lexicographically-sorted local list. - repeated int32 indices = 1; -} - -// The uncompressed threat entries in hash format. -// Hashes can be anywhere from 4 to 32 bytes in size. A large majority are 4 -// bytes, but some hashes are lengthened if they collide with the hash of a -// popular URI. -// -// Used for sending ThreatEntryAdditons to clients that do not support -// compression, or when sending non-4-byte hashes to clients that do support -// compression. -message RawHashes { - // The number of bytes for each prefix encoded below. This field can be - // anywhere from 4 (shortest prefix) to 32 (full SHA256 hash). - // In practice this is almost always 4, except in exceptional circumstances. - int32 prefix_size = 1; - - // The hashes, in binary format, concatenated into one long string. Hashes are - // sorted in lexicographic order. For JSON API users, hashes are - // base64-encoded. - bytes raw_hashes = 2; -} - -// The Rice-Golomb encoded data. Used for sending compressed 4-byte hashes or -// compressed removal indices. -message RiceDeltaEncoding { - // The offset of the first entry in the encoded data, or, if only a single - // integer was encoded, that single integer's value. If the field is empty or - // missing, assume zero. - int64 first_value = 1; - - // The Golomb-Rice parameter, which is a number between 2 and 28. This field - // is missing (that is, zero) if `num_entries` is zero. - int32 rice_parameter = 2; - - // The number of entries that are delta encoded in the encoded data. If only a - // single integer was encoded, this will be zero and the single value will be - // stored in `first_value`. - int32 entry_count = 3; - - // The encoded deltas that are encoded using the Golomb-Rice coder. - bytes encoded_data = 4; -} - -// Wraps a URI that might be displaying phishing content. -message Submission { - // Required. The URI that is being reported for phishing content to be analyzed. - string uri = 1 [(google.api.field_behavior) = REQUIRED]; -} - -// Request to send a potentially phishy URI to WebRisk. -message CreateSubmissionRequest { - // Required. The name of the project that is making the submission. This string is in - // the format "projects/{project_number}". - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "cloudresourcemanager.googleapis.com/Project" - } - ]; - - // Required. The submission that contains the content of the phishing report. - Submission submission = 2 [(google.api.field_behavior) = REQUIRED]; -} diff --git a/google/cloud/webrisk_v1/services/__init__.py b/google/cloud/webrisk_v1/services/__init__.py index 42ffdf2..4de6597 100644 --- a/google/cloud/webrisk_v1/services/__init__.py +++ b/google/cloud/webrisk_v1/services/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/google/cloud/webrisk_v1/services/web_risk_service/__init__.py b/google/cloud/webrisk_v1/services/web_risk_service/__init__.py index 025193e..e5161ab 100644 --- a/google/cloud/webrisk_v1/services/web_risk_service/__init__.py +++ b/google/cloud/webrisk_v1/services/web_risk_service/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .client import WebRiskServiceClient from .async_client import WebRiskServiceAsyncClient diff --git a/google/cloud/webrisk_v1/services/web_risk_service/async_client.py b/google/cloud/webrisk_v1/services/web_risk_service/async_client.py index f92fda2..3d00601 100644 --- a/google/cloud/webrisk_v1/services/web_risk_service/async_client.py +++ b/google/cloud/webrisk_v1/services/web_risk_service/async_client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict import functools import re @@ -22,15 +20,14 @@ import pkg_resources import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore from google.cloud.webrisk_v1.types import webrisk -from google.protobuf import timestamp_pb2 as timestamp # type: ignore - +from google.protobuf import timestamp_pb2 # type: ignore from .transports.base import WebRiskServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import WebRiskServiceGrpcAsyncIOTransport from .client import WebRiskServiceClient @@ -52,24 +49,20 @@ class WebRiskServiceAsyncClient: parse_common_billing_account_path = staticmethod( WebRiskServiceClient.parse_common_billing_account_path ) - common_folder_path = staticmethod(WebRiskServiceClient.common_folder_path) parse_common_folder_path = staticmethod( WebRiskServiceClient.parse_common_folder_path ) - common_organization_path = staticmethod( WebRiskServiceClient.common_organization_path ) parse_common_organization_path = staticmethod( WebRiskServiceClient.parse_common_organization_path ) - common_project_path = staticmethod(WebRiskServiceClient.common_project_path) parse_common_project_path = staticmethod( WebRiskServiceClient.parse_common_project_path ) - common_location_path = staticmethod(WebRiskServiceClient.common_location_path) parse_common_location_path = staticmethod( WebRiskServiceClient.parse_common_location_path @@ -77,7 +70,8 @@ class WebRiskServiceAsyncClient: @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -92,7 +86,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -109,7 +103,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> WebRiskServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: WebRiskServiceTransport: The transport used by the client instance. @@ -123,12 +117,12 @@ def transport(self) -> WebRiskServiceTransport: def __init__( self, *, - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, transport: Union[str, WebRiskServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the web risk service client. + """Instantiates the web risk service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -160,7 +154,6 @@ def __init__( google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. """ - self._client = WebRiskServiceClient( credentials=credentials, transport=transport, @@ -220,7 +213,6 @@ async def compute_threat_list_diff( This corresponds to the ``constraints`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -245,7 +237,6 @@ async def compute_threat_list_diff( # If we have keyword arguments corresponding to fields on the # request, apply these. - if threat_type is not None: request.threat_type = threat_type if version_token is not None: @@ -262,7 +253,8 @@ async def compute_threat_list_diff( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -312,7 +304,6 @@ async def search_uris( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -337,10 +328,8 @@ async def search_uris( # If we have keyword arguments corresponding to fields on the # request, apply these. - if uri is not None: request.uri = uri - if threat_types: request.threat_types.extend(threat_types) @@ -353,7 +342,8 @@ async def search_uris( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -405,7 +395,6 @@ async def search_hashes( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -430,10 +419,8 @@ async def search_hashes( # If we have keyword arguments corresponding to fields on the # request, apply these. - if hash_prefix is not None: request.hash_prefix = hash_prefix - if threat_types: request.threat_types.extend(threat_types) @@ -446,7 +433,8 @@ async def search_hashes( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -499,7 +487,6 @@ async def create_submission( This corresponds to the ``submission`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -526,7 +513,6 @@ async def create_submission( # If we have keyword arguments corresponding to fields on the # request, apply these. - if parent is not None: request.parent = parent if submission is not None: diff --git a/google/cloud/webrisk_v1/services/web_risk_service/client.py b/google/cloud/webrisk_v1/services/web_risk_service/client.py index aa59210..973071a 100644 --- a/google/cloud/webrisk_v1/services/web_risk_service/client.py +++ b/google/cloud/webrisk_v1/services/web_risk_service/client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from distutils import util import os @@ -23,18 +21,17 @@ import pkg_resources from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore from google.cloud.webrisk_v1.types import webrisk -from google.protobuf import timestamp_pb2 as timestamp # type: ignore - +from google.protobuf import timestamp_pb2 # type: ignore from .transports.base import WebRiskServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import WebRiskServiceGrpcTransport from .transports.grpc_asyncio import WebRiskServiceGrpcAsyncIOTransport @@ -55,7 +52,7 @@ class WebRiskServiceClientMeta(type): _transport_registry["grpc_asyncio"] = WebRiskServiceGrpcAsyncIOTransport def get_transport_class(cls, label: str = None,) -> Type[WebRiskServiceTransport]: - """Return an appropriate transport class. + """Returns an appropriate transport class. Args: label: The name of the desired transport. If none is @@ -80,7 +77,8 @@ class WebRiskServiceClient(metaclass=WebRiskServiceClientMeta): @staticmethod def _get_default_mtls_endpoint(api_endpoint): - """Convert api endpoint to mTLS endpoint. + """Converts api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. Args: @@ -114,7 +112,8 @@ def _get_default_mtls_endpoint(api_endpoint): @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -131,7 +130,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -150,16 +149,17 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> WebRiskServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: - WebRiskServiceTransport: The transport used by the client instance. + WebRiskServiceTransport: The transport used by the client + instance. """ return self._transport @staticmethod def common_billing_account_path(billing_account: str,) -> str: - """Return a fully-qualified billing_account string.""" + """Returns a fully-qualified billing_account string.""" return "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -172,7 +172,7 @@ def parse_common_billing_account_path(path: str) -> Dict[str, str]: @staticmethod def common_folder_path(folder: str,) -> str: - """Return a fully-qualified folder string.""" + """Returns a fully-qualified folder string.""" return "folders/{folder}".format(folder=folder,) @staticmethod @@ -183,7 +183,7 @@ def parse_common_folder_path(path: str) -> Dict[str, str]: @staticmethod def common_organization_path(organization: str,) -> str: - """Return a fully-qualified organization string.""" + """Returns a fully-qualified organization string.""" return "organizations/{organization}".format(organization=organization,) @staticmethod @@ -194,7 +194,7 @@ def parse_common_organization_path(path: str) -> Dict[str, str]: @staticmethod def common_project_path(project: str,) -> str: - """Return a fully-qualified project string.""" + """Returns a fully-qualified project string.""" return "projects/{project}".format(project=project,) @staticmethod @@ -205,7 +205,7 @@ def parse_common_project_path(path: str) -> Dict[str, str]: @staticmethod def common_location_path(project: str, location: str,) -> str: - """Return a fully-qualified location string.""" + """Returns a fully-qualified location string.""" return "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -219,12 +219,12 @@ def parse_common_location_path(path: str) -> Dict[str, str]: def __init__( self, *, - credentials: Optional[credentials.Credentials] = None, + credentials: Optional[ga_credentials.Credentials] = None, transport: Union[str, WebRiskServiceTransport, None] = None, client_options: Optional[client_options_lib.ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the web risk service client. + """Instantiates the web risk service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -279,9 +279,10 @@ def __init__( client_cert_source_func = client_options.client_cert_source else: is_mtls = mtls.has_default_client_cert_source() - client_cert_source_func = ( - mtls.default_client_cert_source() if is_mtls else None - ) + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -293,12 +294,14 @@ def __init__( elif use_mtls_env == "always": api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT - ) + if is_mtls: + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = self.DEFAULT_ENDPOINT else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" ) # Save or instantiate the transport. @@ -313,8 +316,8 @@ def __init__( ) if client_options.scopes: raise ValueError( - "When providing a transport instance, " - "provide its scopes directly." + "When providing a transport instance, provide its scopes " + "directly." ) self._transport = transport else: @@ -381,7 +384,6 @@ def compute_threat_list_diff( This corresponds to the ``constraints`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -408,10 +410,8 @@ def compute_threat_list_diff( # there are no flattened fields. if not isinstance(request, webrisk.ComputeThreatListDiffRequest): request = webrisk.ComputeThreatListDiffRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if threat_type is not None: request.threat_type = threat_type if version_token is not None: @@ -465,7 +465,6 @@ def search_uris( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -492,10 +491,8 @@ def search_uris( # there are no flattened fields. if not isinstance(request, webrisk.SearchUrisRequest): request = webrisk.SearchUrisRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if uri is not None: request.uri = uri if threat_types is not None: @@ -549,7 +546,6 @@ def search_hashes( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -576,10 +572,8 @@ def search_hashes( # there are no flattened fields. if not isinstance(request, webrisk.SearchHashesRequest): request = webrisk.SearchHashesRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if hash_prefix is not None: request.hash_prefix = hash_prefix if threat_types is not None: @@ -634,7 +628,6 @@ def create_submission( This corresponds to the ``submission`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -663,10 +656,8 @@ def create_submission( # there are no flattened fields. if not isinstance(request, webrisk.CreateSubmissionRequest): request = webrisk.CreateSubmissionRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if parent is not None: request.parent = parent if submission is not None: diff --git a/google/cloud/webrisk_v1/services/web_risk_service/transports/__init__.py b/google/cloud/webrisk_v1/services/web_risk_service/transports/__init__.py index 5b2203f..f9f94ff 100644 --- a/google/cloud/webrisk_v1/services/web_risk_service/transports/__init__.py +++ b/google/cloud/webrisk_v1/services/web_risk_service/transports/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from typing import Dict, Type diff --git a/google/cloud/webrisk_v1/services/web_risk_service/transports/base.py b/google/cloud/webrisk_v1/services/web_risk_service/transports/base.py index 537f9ac..63b636b 100644 --- a/google/cloud/webrisk_v1/services/web_risk_service/transports/base.py +++ b/google/cloud/webrisk_v1/services/web_risk_service/transports/base.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,20 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import abc -import typing +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union +import packaging.version import pkg_resources -from google import auth # type: ignore -from google.api_core import exceptions # type: ignore +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.cloud.webrisk_v1.types import webrisk - try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution("google-cloud-webrisk",).version, @@ -35,27 +34,41 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() +try: + # google.auth.__version__ was added in 1.26.0 + _GOOGLE_AUTH_VERSION = google.auth.__version__ +except AttributeError: + try: # try pkg_resources if it is available + _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version + except pkg_resources.DistributionNotFound: # pragma: NO COVER + _GOOGLE_AUTH_VERSION = None + +_API_CORE_VERSION = google.api_core.__version__ + class WebRiskServiceTransport(abc.ABC): """Abstract transport class for WebRiskService.""" AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + DEFAULT_HOST: str = "webrisk.googleapis.com" + def __init__( self, *, - host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, - credentials_file: typing.Optional[str] = None, - scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, - quota_project_id: typing.Optional[str] = None, + host: str = DEFAULT_HOST, + credentials: ga_credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -64,7 +77,7 @@ def __init__( credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. This argument is mutually exclusive with credentials. - scope (Optional[Sequence[str]]): A list of scopes. + scopes (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): @@ -78,29 +91,76 @@ def __init__( host += ":443" self._host = host + scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + # 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: - raise exceptions.DuplicateCredentialArgs( + raise core_exceptions.DuplicateCredentialArgs( "'credentials_file' and 'credentials' are mutually exclusive" ) if credentials_file is not None: - credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id ) elif credentials is None: - credentials, _ = auth.default( - scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials + # TODO(busunkim): These two class methods are in the base transport + # to avoid duplicating code across the transport classes. These functions + # should be deleted once the minimum required versions of google-api-core + # and google-auth are increased. + + # TODO: Remove this function once google-auth >= 1.25.0 is required + @classmethod + def _get_scopes_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Optional[Sequence[str]]]: + """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" + + scopes_kwargs = {} + + if _GOOGLE_AUTH_VERSION and ( + packaging.version.parse(_GOOGLE_AUTH_VERSION) + >= packaging.version.parse("1.25.0") + ): + scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} + else: + scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} + + return scopes_kwargs + + # TODO: Remove this function once google-api-core >= 1.26.0 is required + @classmethod + def _get_self_signed_jwt_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Union[Optional[Sequence[str]], str]]: + """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" + + self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} + + if _API_CORE_VERSION and ( + packaging.version.parse(_API_CORE_VERSION) + >= packaging.version.parse("1.26.0") + ): + self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES + self_signed_jwt_kwargs["scopes"] = scopes + self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST + else: + self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES + + return self_signed_jwt_kwargs + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -111,7 +171,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -125,7 +186,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -139,7 +201,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -154,11 +217,11 @@ def _prep_wrapped_messages(self, client_info): @property def compute_threat_list_diff( self, - ) -> typing.Callable[ + ) -> Callable[ [webrisk.ComputeThreatListDiffRequest], - typing.Union[ + Union[ webrisk.ComputeThreatListDiffResponse, - typing.Awaitable[webrisk.ComputeThreatListDiffResponse], + Awaitable[webrisk.ComputeThreatListDiffResponse], ], ]: raise NotImplementedError() @@ -166,31 +229,27 @@ def compute_threat_list_diff( @property def search_uris( self, - ) -> typing.Callable[ + ) -> Callable[ [webrisk.SearchUrisRequest], - typing.Union[ - webrisk.SearchUrisResponse, typing.Awaitable[webrisk.SearchUrisResponse] - ], + Union[webrisk.SearchUrisResponse, Awaitable[webrisk.SearchUrisResponse]], ]: raise NotImplementedError() @property def search_hashes( self, - ) -> typing.Callable[ + ) -> Callable[ [webrisk.SearchHashesRequest], - typing.Union[ - webrisk.SearchHashesResponse, typing.Awaitable[webrisk.SearchHashesResponse] - ], + Union[webrisk.SearchHashesResponse, Awaitable[webrisk.SearchHashesResponse]], ]: raise NotImplementedError() @property def create_submission( self, - ) -> typing.Callable[ + ) -> Callable[ [webrisk.CreateSubmissionRequest], - typing.Union[webrisk.Submission, typing.Awaitable[webrisk.Submission]], + Union[webrisk.Submission, Awaitable[webrisk.Submission]], ]: raise NotImplementedError() diff --git a/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc.py b/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc.py index 203a66d..cec4459 100644 --- a/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc.py +++ b/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,20 +13,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Callable, Dict, Optional, Sequence, Tuple +from typing import Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import grpc_helpers # type: ignore from google.api_core import gapic_v1 # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore import grpc # type: ignore from google.cloud.webrisk_v1.types import webrisk - from .base import WebRiskServiceTransport, DEFAULT_CLIENT_INFO @@ -51,7 +48,7 @@ def __init__( self, *, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Sequence[str] = None, channel: grpc.Channel = None, @@ -65,7 +62,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -175,7 +173,7 @@ def __init__( def create_channel( cls, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -206,13 +204,15 @@ def create_channel( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) diff --git a/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc_asyncio.py b/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc_asyncio.py index ade4db1..871e15e 100644 --- a/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc_asyncio.py +++ b/google/cloud/webrisk_v1/services/web_risk_service/transports/grpc_asyncio.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,21 +13,19 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore +import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore from google.cloud.webrisk_v1.types import webrisk - from .base import WebRiskServiceTransport, DEFAULT_CLIENT_INFO from .grpc import WebRiskServiceGrpcTransport @@ -54,7 +51,7 @@ class WebRiskServiceGrpcAsyncIOTransport(WebRiskServiceTransport): def create_channel( cls, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -81,13 +78,15 @@ def create_channel( Returns: aio.Channel: A gRPC AsyncIO channel object. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) @@ -95,7 +94,7 @@ def __init__( self, *, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, channel: aio.Channel = None, @@ -109,7 +108,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -167,7 +167,6 @@ def __init__( # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - else: if api_mtls_endpoint: host = api_mtls_endpoint diff --git a/google/cloud/webrisk_v1/types/__init__.py b/google/cloud/webrisk_v1/types/__init__.py index fcb4f1f..09cb09c 100644 --- a/google/cloud/webrisk_v1/types/__init__.py +++ b/google/cloud/webrisk_v1/types/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .webrisk import ( ComputeThreatListDiffRequest, ComputeThreatListDiffResponse, diff --git a/google/cloud/webrisk_v1/types/webrisk.py b/google/cloud/webrisk_v1/types/webrisk.py index 5efe7c3..732f1da 100644 --- a/google/cloud/webrisk_v1/types/webrisk.py +++ b/google/cloud/webrisk_v1/types/webrisk.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,11 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - -from google.protobuf import timestamp_pb2 as timestamp # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore __protobuf__ = proto.module( @@ -62,7 +59,6 @@ class CompressionType(proto.Enum): class ComputeThreatListDiffRequest(proto.Message): r"""Describes an API diff request. - Attributes: threat_type (google.cloud.webrisk_v1.types.ThreatType): Required. The threat list to update. Only a @@ -82,7 +78,6 @@ class ComputeThreatListDiffRequest(proto.Message): class Constraints(proto.Message): r"""The constraints for this diff. - Attributes: max_diff_entries (int): The maximum size in number of entries. The diff will not @@ -99,24 +94,19 @@ class Constraints(proto.Message): client. """ - max_diff_entries = proto.Field(proto.INT32, number=1) - - max_database_entries = proto.Field(proto.INT32, number=2) - + max_diff_entries = proto.Field(proto.INT32, number=1,) + max_database_entries = proto.Field(proto.INT32, number=2,) supported_compressions = proto.RepeatedField( proto.ENUM, number=3, enum="CompressionType", ) threat_type = proto.Field(proto.ENUM, number=1, enum="ThreatType",) - - version_token = proto.Field(proto.BYTES, number=2) - + version_token = proto.Field(proto.BYTES, number=2,) constraints = proto.Field(proto.MESSAGE, number=3, message=Constraints,) class ComputeThreatListDiffResponse(proto.Message): r""" - Attributes: response_type (google.cloud.webrisk_v1.types.ComputeThreatListDiffResponse.ResponseType): The type of response. This may indicate that @@ -157,7 +147,6 @@ class ResponseType(proto.Enum): class Checksum(proto.Message): r"""The expected state of a client's local database. - Attributes: sha256 (bytes): The SHA256 hash of the client state; that is, @@ -165,26 +154,20 @@ class Checksum(proto.Message): database. """ - sha256 = proto.Field(proto.BYTES, number=1) + sha256 = proto.Field(proto.BYTES, number=1,) response_type = proto.Field(proto.ENUM, number=4, enum=ResponseType,) - additions = proto.Field(proto.MESSAGE, number=5, message="ThreatEntryAdditions",) - removals = proto.Field(proto.MESSAGE, number=6, message="ThreatEntryRemovals",) - - new_version_token = proto.Field(proto.BYTES, number=7) - + new_version_token = proto.Field(proto.BYTES, number=7,) checksum = proto.Field(proto.MESSAGE, number=8, message=Checksum,) - recommended_next_diff = proto.Field( - proto.MESSAGE, number=2, message=timestamp.Timestamp, + proto.MESSAGE, number=2, message=timestamp_pb2.Timestamp, ) class SearchUrisRequest(proto.Message): r"""Request to check URI entries against threatLists. - Attributes: uri (str): Required. The URI to be checked for matches. @@ -193,14 +176,12 @@ class SearchUrisRequest(proto.Message): Multiple ThreatLists may be specified. """ - uri = proto.Field(proto.STRING, number=1) - + uri = proto.Field(proto.STRING, number=1,) threat_types = proto.RepeatedField(proto.ENUM, number=2, enum="ThreatType",) class SearchUrisResponse(proto.Message): r""" - Attributes: threat (google.cloud.webrisk_v1.types.SearchUrisResponse.ThreatUri): The threat list matches. This may be empty if @@ -209,7 +190,6 @@ class SearchUrisResponse(proto.Message): class ThreatUri(proto.Message): r"""Contains threat information on a matching uri. - Attributes: threat_types (Sequence[google.cloud.webrisk_v1.types.ThreatType]): The ThreatList this threat belongs to. @@ -220,8 +200,9 @@ class ThreatUri(proto.Message): """ threat_types = proto.RepeatedField(proto.ENUM, number=1, enum="ThreatType",) - - expire_time = proto.Field(proto.MESSAGE, number=2, message=timestamp.Timestamp,) + expire_time = proto.Field( + proto.MESSAGE, number=2, message=timestamp_pb2.Timestamp, + ) threat = proto.Field(proto.MESSAGE, number=1, message=ThreatUri,) @@ -240,14 +221,12 @@ class SearchHashesRequest(proto.Message): Multiple ThreatLists may be specified. """ - hash_prefix = proto.Field(proto.BYTES, number=1) - + hash_prefix = proto.Field(proto.BYTES, number=1,) threat_types = proto.RepeatedField(proto.ENUM, number=2, enum="ThreatType",) class SearchHashesResponse(proto.Message): r""" - Attributes: threats (Sequence[google.cloud.webrisk_v1.types.SearchHashesResponse.ThreatHash]): The full hashes that matched the requested @@ -260,7 +239,6 @@ class SearchHashesResponse(proto.Message): class ThreatHash(proto.Message): r"""Contains threat information on a matching hash. - Attributes: threat_types (Sequence[google.cloud.webrisk_v1.types.ThreatType]): The ThreatList this threat belongs to. @@ -276,15 +254,14 @@ class ThreatHash(proto.Message): """ threat_types = proto.RepeatedField(proto.ENUM, number=1, enum="ThreatType",) - - hash_ = proto.Field(proto.BYTES, number=2) - - expire_time = proto.Field(proto.MESSAGE, number=3, message=timestamp.Timestamp,) + hash_ = proto.Field(proto.BYTES, number=2,) + expire_time = proto.Field( + proto.MESSAGE, number=3, message=timestamp_pb2.Timestamp, + ) threats = proto.RepeatedField(proto.MESSAGE, number=1, message=ThreatHash,) - negative_expire_time = proto.Field( - proto.MESSAGE, number=2, message=timestamp.Timestamp, + proto.MESSAGE, number=2, message=timestamp_pb2.Timestamp, ) @@ -306,13 +283,11 @@ class ThreatEntryAdditions(proto.Message): """ raw_hashes = proto.RepeatedField(proto.MESSAGE, number=1, message="RawHashes",) - rice_hashes = proto.Field(proto.MESSAGE, number=2, message="RiceDeltaEncoding",) class ThreatEntryRemovals(proto.Message): r"""Contains the set of entries to remove from a local database. - Attributes: raw_indices (google.cloud.webrisk_v1.types.RawIndices): The raw removal indices for a local list. @@ -325,20 +300,18 @@ class ThreatEntryRemovals(proto.Message): """ raw_indices = proto.Field(proto.MESSAGE, number=1, message="RawIndices",) - rice_indices = proto.Field(proto.MESSAGE, number=2, message="RiceDeltaEncoding",) class RawIndices(proto.Message): r"""A set of raw indices to remove from a local list. - Attributes: indices (Sequence[int]): The indices to remove from a lexicographically-sorted local list. """ - indices = proto.RepeatedField(proto.INT32, number=1) + indices = proto.RepeatedField(proto.INT32, number=1,) class RawHashes(proto.Message): @@ -365,9 +338,8 @@ class RawHashes(proto.Message): are base64-encoded. """ - prefix_size = proto.Field(proto.INT32, number=1) - - raw_hashes = proto.Field(proto.BYTES, number=2) + prefix_size = proto.Field(proto.INT32, number=1,) + raw_hashes = proto.Field(proto.BYTES, number=2,) class RiceDeltaEncoding(proto.Message): @@ -393,30 +365,25 @@ class RiceDeltaEncoding(proto.Message): Golomb-Rice coder. """ - first_value = proto.Field(proto.INT64, number=1) - - rice_parameter = proto.Field(proto.INT32, number=2) - - entry_count = proto.Field(proto.INT32, number=3) - - encoded_data = proto.Field(proto.BYTES, number=4) + first_value = proto.Field(proto.INT64, number=1,) + rice_parameter = proto.Field(proto.INT32, number=2,) + entry_count = proto.Field(proto.INT32, number=3,) + encoded_data = proto.Field(proto.BYTES, number=4,) class Submission(proto.Message): r"""Wraps a URI that might be displaying phishing content. - Attributes: uri (str): Required. The URI that is being reported for phishing content to be analyzed. """ - uri = proto.Field(proto.STRING, number=1) + uri = proto.Field(proto.STRING, number=1,) class CreateSubmissionRequest(proto.Message): r"""Request to send a potentially phishy URI to WebRisk. - Attributes: parent (str): Required. The name of the project that is making the @@ -427,8 +394,7 @@ class CreateSubmissionRequest(proto.Message): content of the phishing report. """ - parent = proto.Field(proto.STRING, number=1) - + parent = proto.Field(proto.STRING, number=1,) submission = proto.Field(proto.MESSAGE, number=2, message="Submission",) diff --git a/google/cloud/webrisk_v1beta1/__init__.py b/google/cloud/webrisk_v1beta1/__init__.py index 3128dd4..44e8c21 100644 --- a/google/cloud/webrisk_v1beta1/__init__.py +++ b/google/cloud/webrisk_v1beta1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +15,8 @@ # from .services.web_risk_service_v1_beta1 import WebRiskServiceV1Beta1Client -from .types.webrisk import CompressionType +from .services.web_risk_service_v1_beta1 import WebRiskServiceV1Beta1AsyncClient + from .types.webrisk import ComputeThreatListDiffRequest from .types.webrisk import ComputeThreatListDiffResponse from .types.webrisk import RawHashes @@ -28,10 +28,11 @@ from .types.webrisk import SearchUrisResponse from .types.webrisk import ThreatEntryAdditions from .types.webrisk import ThreatEntryRemovals +from .types.webrisk import CompressionType from .types.webrisk import ThreatType - __all__ = ( + "WebRiskServiceV1Beta1AsyncClient", "CompressionType", "ComputeThreatListDiffRequest", "ComputeThreatListDiffResponse", diff --git a/google/cloud/webrisk_v1beta1/gapic_metadata.json b/google/cloud/webrisk_v1beta1/gapic_metadata.json new file mode 100644 index 0000000..64df094 --- /dev/null +++ b/google/cloud/webrisk_v1beta1/gapic_metadata.json @@ -0,0 +1,53 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.webrisk_v1beta1", + "protoPackage": "google.cloud.webrisk.v1beta1", + "schema": "1.0", + "services": { + "WebRiskServiceV1Beta1": { + "clients": { + "grpc": { + "libraryClient": "WebRiskServiceV1Beta1Client", + "rpcs": { + "ComputeThreatListDiff": { + "methods": [ + "compute_threat_list_diff" + ] + }, + "SearchHashes": { + "methods": [ + "search_hashes" + ] + }, + "SearchUris": { + "methods": [ + "search_uris" + ] + } + } + }, + "grpc-async": { + "libraryClient": "WebRiskServiceV1Beta1AsyncClient", + "rpcs": { + "ComputeThreatListDiff": { + "methods": [ + "compute_threat_list_diff" + ] + }, + "SearchHashes": { + "methods": [ + "search_hashes" + ] + }, + "SearchUris": { + "methods": [ + "search_uris" + ] + } + } + } + } + } + } +} diff --git a/google/cloud/webrisk_v1beta1/proto/webrisk.proto b/google/cloud/webrisk_v1beta1/proto/webrisk.proto deleted file mode 100644 index 0226425..0000000 --- a/google/cloud/webrisk_v1beta1/proto/webrisk.proto +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2019 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. -// - -syntax = "proto3"; - -package google.cloud.webrisk.v1beta1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/protobuf/timestamp.proto"; - -option csharp_namespace = "Google.Cloud.WebRisk.V1Beta1"; -option go_package = "google.golang.org/genproto/googleapis/cloud/webrisk/v1beta1;webrisk"; -option java_multiple_files = true; -option java_outer_classname = "WebRiskProto"; -option java_package = "com.google.webrisk.v1beta1"; -option objc_class_prefix = "GCWR"; -option php_namespace = "Google\\Cloud\\WebRisk\\V1beta1"; -option ruby_package = "Google::Cloud::WebRisk::V1beta1"; - -// Web Risk v1beta1 API defines an interface to detect malicious URLs on your -// website and in client applications. -service WebRiskServiceV1Beta1 { - option (google.api.default_host) = "webrisk.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Gets the most recent threat list diffs. - rpc ComputeThreatListDiff(ComputeThreatListDiffRequest) returns (ComputeThreatListDiffResponse) { - option (google.api.http) = { - get: "/v1beta1/threatLists:computeDiff" - }; - option (google.api.method_signature) = "threat_type,version_token,constraints"; - } - - // This method is used to check whether a URI is on a given threatList. - rpc SearchUris(SearchUrisRequest) returns (SearchUrisResponse) { - option (google.api.http) = { - get: "/v1beta1/uris:search" - }; - option (google.api.method_signature) = "uri,threat_types"; - } - - // Gets the full hashes that match the requested hash prefix. - // This is used after a hash prefix is looked up in a threatList - // and there is a match. The client side threatList only holds partial hashes - // so the client must query this method to determine if there is a full - // hash match of a threat. - rpc SearchHashes(SearchHashesRequest) returns (SearchHashesResponse) { - option (google.api.http) = { - get: "/v1beta1/hashes:search" - }; - option (google.api.method_signature) = "hash_prefix,threat_types"; - } -} - -// Describes an API diff request. -message ComputeThreatListDiffRequest { - // The constraints for this diff. - message Constraints { - // The maximum size in number of entries. The diff will not contain more - // entries than this value. This should be a power of 2 between 2**10 and - // 2**20. If zero, no diff size limit is set. - int32 max_diff_entries = 1; - - // Sets the maximum number of entries that the client is willing to have - // in the local database. This should be a power of 2 between 2**10 and - // 2**20. If zero, no database size limit is set. - int32 max_database_entries = 2; - - // The compression types supported by the client. - repeated CompressionType supported_compressions = 3; - } - - // The ThreatList to update. - ThreatType threat_type = 1 [(google.api.field_behavior) = REQUIRED]; - - // The current version token of the client for the requested list (the - // client version that was received from the last successful diff). - bytes version_token = 2; - - // Required. The constraints associated with this request. - Constraints constraints = 3 [(google.api.field_behavior) = REQUIRED]; -} - -message ComputeThreatListDiffResponse { - // The expected state of a client's local database. - message Checksum { - // The SHA256 hash of the client state; that is, of the sorted list of all - // hashes present in the database. - bytes sha256 = 1; - } - - // The type of response sent to the client. - enum ResponseType { - // Unknown. - RESPONSE_TYPE_UNSPECIFIED = 0; - - // Partial updates are applied to the client's existing local database. - DIFF = 1; - - // Full updates resets the client's entire local database. This means - // that either the client had no state, was seriously out-of-date, - // or the client is believed to be corrupt. - RESET = 2; - } - - // The type of response. This may indicate that an action must be taken by the - // client when the response is received. - ResponseType response_type = 4; - - // A set of entries to add to a local threat type's list. - ThreatEntryAdditions additions = 5; - - // A set of entries to remove from a local threat type's list. - // This field may be empty. - ThreatEntryRemovals removals = 6; - - // The new opaque client version token. - bytes new_version_token = 7; - - // The expected SHA256 hash of the client state; that is, of the sorted list - // of all hashes present in the database after applying the provided diff. - // If the client state doesn't match the expected state, the client must - // disregard this diff and retry later. - Checksum checksum = 8; - - // The soonest the client should wait before issuing any diff - // request. Querying sooner is unlikely to produce a meaningful diff. - // Waiting longer is acceptable considering the use case. - // If this field is not set clients may update as soon as they want. - google.protobuf.Timestamp recommended_next_diff = 2; -} - -// Request to check URI entries against threatLists. -message SearchUrisRequest { - // Required. The URI to be checked for matches. - string uri = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The ThreatLists to search in. - repeated ThreatType threat_types = 2 [(google.api.field_behavior) = REQUIRED]; -} - -message SearchUrisResponse { - // Contains threat information on a matching uri. - message ThreatUri { - // The ThreatList this threat belongs to. - repeated ThreatType threat_types = 1; - - // The cache lifetime for the returned match. Clients must not cache this - // response past this timestamp to avoid false positives. - google.protobuf.Timestamp expire_time = 2; - } - - // The threat list matches. This may be empty if the URI is on no list. - ThreatUri threat = 1; -} - -// Request to return full hashes matched by the provided hash prefixes. -message SearchHashesRequest { - // A hash prefix, consisting of the most significant 4-32 bytes of a SHA256 - // hash. For JSON requests, this field is base64-encoded. - bytes hash_prefix = 1; - - // Required. The ThreatLists to search in. - repeated ThreatType threat_types = 2 [(google.api.field_behavior) = REQUIRED]; -} - -message SearchHashesResponse { - // Contains threat information on a matching hash. - message ThreatHash { - // The ThreatList this threat belongs to. - // This must contain at least one entry. - repeated ThreatType threat_types = 1; - - // A 32 byte SHA256 hash. This field is in binary format. For JSON - // requests, hashes are base64-encoded. - bytes hash = 2; - - // The cache lifetime for the returned match. Clients must not cache this - // response past this timestamp to avoid false positives. - google.protobuf.Timestamp expire_time = 3; - } - - // The full hashes that matched the requested prefixes. - // The hash will be populated in the key. - repeated ThreatHash threats = 1; - - // For requested entities that did not match the threat list, how long to - // cache the response until. - google.protobuf.Timestamp negative_expire_time = 2; -} - -// Contains the set of entries to add to a local database. -// May contain a combination of compressed and raw data in a single response. -message ThreatEntryAdditions { - // The raw SHA256-formatted entries. - // Repeated to allow returning sets of hashes with different prefix sizes. - repeated RawHashes raw_hashes = 1; - - // The encoded 4-byte prefixes of SHA256-formatted entries, using a - // Golomb-Rice encoding. The hashes are converted to uint32, sorted in - // ascending order, then delta encoded and stored as encoded_data. - RiceDeltaEncoding rice_hashes = 2; -} - -// Contains the set of entries to remove from a local database. -message ThreatEntryRemovals { - // The raw removal indices for a local list. - RawIndices raw_indices = 1; - - // The encoded local, lexicographically-sorted list indices, using a - // Golomb-Rice encoding. Used for sending compressed removal indices. The - // removal indices (uint32) are sorted in ascending order, then delta encoded - // and stored as encoded_data. - RiceDeltaEncoding rice_indices = 2; -} - -// The type of threat. This maps dirrectly to the threat list a threat may -// belong to. -enum ThreatType { - // Unknown. - THREAT_TYPE_UNSPECIFIED = 0; - - // Malware targeting any platform. - MALWARE = 1; - - // Social engineering targeting any platform. - SOCIAL_ENGINEERING = 2; - - // Unwanted software targeting any platform. - UNWANTED_SOFTWARE = 3; -} - -// The ways in which threat entry sets can be compressed. -enum CompressionType { - // Unknown. - COMPRESSION_TYPE_UNSPECIFIED = 0; - - // Raw, uncompressed data. - RAW = 1; - - // Rice-Golomb encoded data. - RICE = 2; -} - -// A set of raw indices to remove from a local list. -message RawIndices { - // The indices to remove from a lexicographically-sorted local list. - repeated int32 indices = 1; -} - -// The uncompressed threat entries in hash format. -// Hashes can be anywhere from 4 to 32 bytes in size. A large majority are 4 -// bytes, but some hashes are lengthened if they collide with the hash of a -// popular URI. -// -// Used for sending ThreatEntryAdditons to clients that do not support -// compression, or when sending non-4-byte hashes to clients that do support -// compression. -message RawHashes { - // The number of bytes for each prefix encoded below. This field can be - // anywhere from 4 (shortest prefix) to 32 (full SHA256 hash). - int32 prefix_size = 1; - - // The hashes, in binary format, concatenated into one long string. Hashes are - // sorted in lexicographic order. For JSON API users, hashes are - // base64-encoded. - bytes raw_hashes = 2; -} - -// The Rice-Golomb encoded data. Used for sending compressed 4-byte hashes or -// compressed removal indices. -message RiceDeltaEncoding { - // The offset of the first entry in the encoded data, or, if only a single - // integer was encoded, that single integer's value. If the field is empty or - // missing, assume zero. - int64 first_value = 1; - - // The Golomb-Rice parameter, which is a number between 2 and 28. This field - // is missing (that is, zero) if `num_entries` is zero. - int32 rice_parameter = 2; - - // The number of entries that are delta encoded in the encoded data. If only a - // single integer was encoded, this will be zero and the single value will be - // stored in `first_value`. - int32 entry_count = 3; - - // The encoded deltas that are encoded using the Golomb-Rice coder. - bytes encoded_data = 4; -} diff --git a/google/cloud/webrisk_v1beta1/services/__init__.py b/google/cloud/webrisk_v1beta1/services/__init__.py index 42ffdf2..4de6597 100644 --- a/google/cloud/webrisk_v1beta1/services/__init__.py +++ b/google/cloud/webrisk_v1beta1/services/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/__init__.py b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/__init__.py index 2c81da5..e88b77e 100644 --- a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/__init__.py +++ b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .client import WebRiskServiceV1Beta1Client from .async_client import WebRiskServiceV1Beta1AsyncClient diff --git a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/async_client.py b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/async_client.py index 3c5072e..2bf114c 100644 --- a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/async_client.py +++ b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/async_client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict import functools import re @@ -22,15 +20,14 @@ import pkg_resources import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore from google.cloud.webrisk_v1beta1.types import webrisk -from google.protobuf import timestamp_pb2 as timestamp # type: ignore - +from google.protobuf import timestamp_pb2 # type: ignore from .transports.base import WebRiskServiceV1Beta1Transport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import WebRiskServiceV1Beta1GrpcAsyncIOTransport from .client import WebRiskServiceV1Beta1Client @@ -52,24 +49,20 @@ class WebRiskServiceV1Beta1AsyncClient: parse_common_billing_account_path = staticmethod( WebRiskServiceV1Beta1Client.parse_common_billing_account_path ) - common_folder_path = staticmethod(WebRiskServiceV1Beta1Client.common_folder_path) parse_common_folder_path = staticmethod( WebRiskServiceV1Beta1Client.parse_common_folder_path ) - common_organization_path = staticmethod( WebRiskServiceV1Beta1Client.common_organization_path ) parse_common_organization_path = staticmethod( WebRiskServiceV1Beta1Client.parse_common_organization_path ) - common_project_path = staticmethod(WebRiskServiceV1Beta1Client.common_project_path) parse_common_project_path = staticmethod( WebRiskServiceV1Beta1Client.parse_common_project_path ) - common_location_path = staticmethod( WebRiskServiceV1Beta1Client.common_location_path ) @@ -79,7 +72,8 @@ class WebRiskServiceV1Beta1AsyncClient: @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -94,7 +88,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -111,7 +105,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> WebRiskServiceV1Beta1Transport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: WebRiskServiceV1Beta1Transport: The transport used by the client instance. @@ -126,12 +120,12 @@ def transport(self) -> WebRiskServiceV1Beta1Transport: def __init__( self, *, - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, transport: Union[str, WebRiskServiceV1Beta1Transport] = "grpc_asyncio", client_options: ClientOptions = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the web risk service v1 beta1 client. + """Instantiates the web risk service v1 beta1 client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -163,7 +157,6 @@ def __init__( google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. """ - self._client = WebRiskServiceV1Beta1Client( credentials=credentials, transport=transport, @@ -208,7 +201,6 @@ async def compute_threat_list_diff( This corresponds to the ``constraints`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -233,7 +225,6 @@ async def compute_threat_list_diff( # If we have keyword arguments corresponding to fields on the # request, apply these. - if threat_type is not None: request.threat_type = threat_type if version_token is not None: @@ -250,7 +241,8 @@ async def compute_threat_list_diff( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -295,7 +287,6 @@ async def search_uris( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -320,10 +311,8 @@ async def search_uris( # If we have keyword arguments corresponding to fields on the # request, apply these. - if uri is not None: request.uri = uri - if threat_types: request.threat_types.extend(threat_types) @@ -336,7 +325,8 @@ async def search_uris( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -387,7 +377,6 @@ async def search_hashes( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -412,10 +401,8 @@ async def search_hashes( # If we have keyword arguments corresponding to fields on the # request, apply these. - if hash_prefix is not None: request.hash_prefix = hash_prefix - if threat_types: request.threat_types.extend(threat_types) @@ -428,7 +415,8 @@ async def search_hashes( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), diff --git a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/client.py b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/client.py index 36b5b8a..a110fc4 100644 --- a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/client.py +++ b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from distutils import util import os @@ -23,18 +21,17 @@ import pkg_resources from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore from google.cloud.webrisk_v1beta1.types import webrisk -from google.protobuf import timestamp_pb2 as timestamp # type: ignore - +from google.protobuf import timestamp_pb2 # type: ignore from .transports.base import WebRiskServiceV1Beta1Transport, DEFAULT_CLIENT_INFO from .transports.grpc import WebRiskServiceV1Beta1GrpcTransport from .transports.grpc_asyncio import WebRiskServiceV1Beta1GrpcAsyncIOTransport @@ -57,7 +54,7 @@ class WebRiskServiceV1Beta1ClientMeta(type): def get_transport_class( cls, label: str = None, ) -> Type[WebRiskServiceV1Beta1Transport]: - """Return an appropriate transport class. + """Returns an appropriate transport class. Args: label: The name of the desired transport. If none is @@ -82,7 +79,8 @@ class WebRiskServiceV1Beta1Client(metaclass=WebRiskServiceV1Beta1ClientMeta): @staticmethod def _get_default_mtls_endpoint(api_endpoint): - """Convert api endpoint to mTLS endpoint. + """Converts api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. Args: @@ -116,7 +114,8 @@ def _get_default_mtls_endpoint(api_endpoint): @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -133,7 +132,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -152,16 +151,17 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> WebRiskServiceV1Beta1Transport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: - WebRiskServiceV1Beta1Transport: The transport used by the client instance. + WebRiskServiceV1Beta1Transport: The transport used by the client + instance. """ return self._transport @staticmethod def common_billing_account_path(billing_account: str,) -> str: - """Return a fully-qualified billing_account string.""" + """Returns a fully-qualified billing_account string.""" return "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -174,7 +174,7 @@ def parse_common_billing_account_path(path: str) -> Dict[str, str]: @staticmethod def common_folder_path(folder: str,) -> str: - """Return a fully-qualified folder string.""" + """Returns a fully-qualified folder string.""" return "folders/{folder}".format(folder=folder,) @staticmethod @@ -185,7 +185,7 @@ def parse_common_folder_path(path: str) -> Dict[str, str]: @staticmethod def common_organization_path(organization: str,) -> str: - """Return a fully-qualified organization string.""" + """Returns a fully-qualified organization string.""" return "organizations/{organization}".format(organization=organization,) @staticmethod @@ -196,7 +196,7 @@ def parse_common_organization_path(path: str) -> Dict[str, str]: @staticmethod def common_project_path(project: str,) -> str: - """Return a fully-qualified project string.""" + """Returns a fully-qualified project string.""" return "projects/{project}".format(project=project,) @staticmethod @@ -207,7 +207,7 @@ def parse_common_project_path(path: str) -> Dict[str, str]: @staticmethod def common_location_path(project: str, location: str,) -> str: - """Return a fully-qualified location string.""" + """Returns a fully-qualified location string.""" return "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -221,12 +221,12 @@ def parse_common_location_path(path: str) -> Dict[str, str]: def __init__( self, *, - credentials: Optional[credentials.Credentials] = None, + credentials: Optional[ga_credentials.Credentials] = None, transport: Union[str, WebRiskServiceV1Beta1Transport, None] = None, client_options: Optional[client_options_lib.ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the web risk service v1 beta1 client. + """Instantiates the web risk service v1 beta1 client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -281,9 +281,10 @@ def __init__( client_cert_source_func = client_options.client_cert_source else: is_mtls = mtls.has_default_client_cert_source() - client_cert_source_func = ( - mtls.default_client_cert_source() if is_mtls else None - ) + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -295,12 +296,14 @@ def __init__( elif use_mtls_env == "always": api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT - ) + if is_mtls: + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = self.DEFAULT_ENDPOINT else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" ) # Save or instantiate the transport. @@ -315,8 +318,8 @@ def __init__( ) if client_options.scopes: raise ValueError( - "When providing a transport instance, " - "provide its scopes directly." + "When providing a transport instance, provide its scopes " + "directly." ) self._transport = transport else: @@ -368,7 +371,6 @@ def compute_threat_list_diff( This corresponds to the ``constraints`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -395,10 +397,8 @@ def compute_threat_list_diff( # there are no flattened fields. if not isinstance(request, webrisk.ComputeThreatListDiffRequest): request = webrisk.ComputeThreatListDiffRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if threat_type is not None: request.threat_type = threat_type if version_token is not None: @@ -447,7 +447,6 @@ def search_uris( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -474,10 +473,8 @@ def search_uris( # there are no flattened fields. if not isinstance(request, webrisk.SearchUrisRequest): request = webrisk.SearchUrisRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if uri is not None: request.uri = uri if threat_types is not None: @@ -530,7 +527,6 @@ def search_hashes( This corresponds to the ``threat_types`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -557,10 +553,8 @@ def search_hashes( # there are no flattened fields. if not isinstance(request, webrisk.SearchHashesRequest): request = webrisk.SearchHashesRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if hash_prefix is not None: request.hash_prefix = hash_prefix if threat_types is not None: diff --git a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/__init__.py b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/__init__.py index 7dbf769..2c23497 100644 --- a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/__init__.py +++ b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from typing import Dict, Type diff --git a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/base.py b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/base.py index e35f546..7f94a0c 100644 --- a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/base.py +++ b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/base.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,20 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import abc -import typing +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union +import packaging.version import pkg_resources -from google import auth # type: ignore -from google.api_core import exceptions # type: ignore +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.cloud.webrisk_v1beta1.types import webrisk - try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution("google-cloud-webrisk",).version, @@ -35,27 +34,41 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() +try: + # google.auth.__version__ was added in 1.26.0 + _GOOGLE_AUTH_VERSION = google.auth.__version__ +except AttributeError: + try: # try pkg_resources if it is available + _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version + except pkg_resources.DistributionNotFound: # pragma: NO COVER + _GOOGLE_AUTH_VERSION = None + +_API_CORE_VERSION = google.api_core.__version__ + class WebRiskServiceV1Beta1Transport(abc.ABC): """Abstract transport class for WebRiskServiceV1Beta1.""" AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + DEFAULT_HOST: str = "webrisk.googleapis.com" + def __init__( self, *, - host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, - credentials_file: typing.Optional[str] = None, - scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, - quota_project_id: typing.Optional[str] = None, + host: str = DEFAULT_HOST, + credentials: ga_credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -64,7 +77,7 @@ def __init__( credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. This argument is mutually exclusive with credentials. - scope (Optional[Sequence[str]]): A list of scopes. + scopes (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): @@ -78,29 +91,76 @@ def __init__( host += ":443" self._host = host + scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + # 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: - raise exceptions.DuplicateCredentialArgs( + raise core_exceptions.DuplicateCredentialArgs( "'credentials_file' and 'credentials' are mutually exclusive" ) if credentials_file is not None: - credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id ) elif credentials is None: - credentials, _ = auth.default( - scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials + # TODO(busunkim): These two class methods are in the base transport + # to avoid duplicating code across the transport classes. These functions + # should be deleted once the minimum required versions of google-api-core + # and google-auth are increased. + + # TODO: Remove this function once google-auth >= 1.25.0 is required + @classmethod + def _get_scopes_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Optional[Sequence[str]]]: + """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" + + scopes_kwargs = {} + + if _GOOGLE_AUTH_VERSION and ( + packaging.version.parse(_GOOGLE_AUTH_VERSION) + >= packaging.version.parse("1.25.0") + ): + scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} + else: + scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} + + return scopes_kwargs + + # TODO: Remove this function once google-api-core >= 1.26.0 is required + @classmethod + def _get_self_signed_jwt_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Union[Optional[Sequence[str]], str]]: + """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" + + self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} + + if _API_CORE_VERSION and ( + packaging.version.parse(_API_CORE_VERSION) + >= packaging.version.parse("1.26.0") + ): + self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES + self_signed_jwt_kwargs["scopes"] = scopes + self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST + else: + self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES + + return self_signed_jwt_kwargs + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -111,7 +171,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -125,7 +186,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -139,7 +201,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=600.0, ), @@ -151,11 +214,11 @@ def _prep_wrapped_messages(self, client_info): @property def compute_threat_list_diff( self, - ) -> typing.Callable[ + ) -> Callable[ [webrisk.ComputeThreatListDiffRequest], - typing.Union[ + Union[ webrisk.ComputeThreatListDiffResponse, - typing.Awaitable[webrisk.ComputeThreatListDiffResponse], + Awaitable[webrisk.ComputeThreatListDiffResponse], ], ]: raise NotImplementedError() @@ -163,22 +226,18 @@ def compute_threat_list_diff( @property def search_uris( self, - ) -> typing.Callable[ + ) -> Callable[ [webrisk.SearchUrisRequest], - typing.Union[ - webrisk.SearchUrisResponse, typing.Awaitable[webrisk.SearchUrisResponse] - ], + Union[webrisk.SearchUrisResponse, Awaitable[webrisk.SearchUrisResponse]], ]: raise NotImplementedError() @property def search_hashes( self, - ) -> typing.Callable[ + ) -> Callable[ [webrisk.SearchHashesRequest], - typing.Union[ - webrisk.SearchHashesResponse, typing.Awaitable[webrisk.SearchHashesResponse] - ], + Union[webrisk.SearchHashesResponse, Awaitable[webrisk.SearchHashesResponse]], ]: raise NotImplementedError() diff --git a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc.py b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc.py index 3fc4e39..72fcce2 100644 --- a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc.py +++ b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,20 +13,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Callable, Dict, Optional, Sequence, Tuple +from typing import Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import grpc_helpers # type: ignore from google.api_core import gapic_v1 # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore import grpc # type: ignore from google.cloud.webrisk_v1beta1.types import webrisk - from .base import WebRiskServiceV1Beta1Transport, DEFAULT_CLIENT_INFO @@ -51,7 +48,7 @@ def __init__( self, *, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Sequence[str] = None, channel: grpc.Channel = None, @@ -65,7 +62,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -175,7 +173,7 @@ def __init__( def create_channel( cls, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -206,13 +204,15 @@ def create_channel( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) diff --git a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc_asyncio.py b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc_asyncio.py index 292ffd7..2c86182 100644 --- a/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc_asyncio.py +++ b/google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc_asyncio.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,21 +13,19 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore +import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore from google.cloud.webrisk_v1beta1.types import webrisk - from .base import WebRiskServiceV1Beta1Transport, DEFAULT_CLIENT_INFO from .grpc import WebRiskServiceV1Beta1GrpcTransport @@ -54,7 +51,7 @@ class WebRiskServiceV1Beta1GrpcAsyncIOTransport(WebRiskServiceV1Beta1Transport): def create_channel( cls, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -81,13 +78,15 @@ def create_channel( Returns: aio.Channel: A gRPC AsyncIO channel object. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) @@ -95,7 +94,7 @@ def __init__( self, *, host: str = "webrisk.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, channel: aio.Channel = None, @@ -109,7 +108,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -167,7 +167,6 @@ def __init__( # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - else: if api_mtls_endpoint: host = api_mtls_endpoint diff --git a/google/cloud/webrisk_v1beta1/types/__init__.py b/google/cloud/webrisk_v1beta1/types/__init__.py index 81db104..0f161e5 100644 --- a/google/cloud/webrisk_v1beta1/types/__init__.py +++ b/google/cloud/webrisk_v1beta1/types/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .webrisk import ( ComputeThreatListDiffRequest, ComputeThreatListDiffResponse, diff --git a/google/cloud/webrisk_v1beta1/types/webrisk.py b/google/cloud/webrisk_v1beta1/types/webrisk.py index 9ad74b2..89fd31f 100644 --- a/google/cloud/webrisk_v1beta1/types/webrisk.py +++ b/google/cloud/webrisk_v1beta1/types/webrisk.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,11 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - -from google.protobuf import timestamp_pb2 as timestamp # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore __protobuf__ = proto.module( @@ -60,7 +57,6 @@ class CompressionType(proto.Enum): class ComputeThreatListDiffRequest(proto.Message): r"""Describes an API diff request. - Attributes: threat_type (google.cloud.webrisk_v1beta1.types.ThreatType): The ThreatList to update. @@ -75,7 +71,6 @@ class ComputeThreatListDiffRequest(proto.Message): class Constraints(proto.Message): r"""The constraints for this diff. - Attributes: max_diff_entries (int): The maximum size in number of entries. The diff will not @@ -92,24 +87,19 @@ class Constraints(proto.Message): client. """ - max_diff_entries = proto.Field(proto.INT32, number=1) - - max_database_entries = proto.Field(proto.INT32, number=2) - + max_diff_entries = proto.Field(proto.INT32, number=1,) + max_database_entries = proto.Field(proto.INT32, number=2,) supported_compressions = proto.RepeatedField( proto.ENUM, number=3, enum="CompressionType", ) threat_type = proto.Field(proto.ENUM, number=1, enum="ThreatType",) - - version_token = proto.Field(proto.BYTES, number=2) - + version_token = proto.Field(proto.BYTES, number=2,) constraints = proto.Field(proto.MESSAGE, number=3, message=Constraints,) class ComputeThreatListDiffResponse(proto.Message): r""" - Attributes: response_type (google.cloud.webrisk_v1beta1.types.ComputeThreatListDiffResponse.ResponseType): The type of response. This may indicate that @@ -147,7 +137,6 @@ class ResponseType(proto.Enum): class Checksum(proto.Message): r"""The expected state of a client's local database. - Attributes: sha256 (bytes): The SHA256 hash of the client state; that is, @@ -155,26 +144,20 @@ class Checksum(proto.Message): database. """ - sha256 = proto.Field(proto.BYTES, number=1) + sha256 = proto.Field(proto.BYTES, number=1,) response_type = proto.Field(proto.ENUM, number=4, enum=ResponseType,) - additions = proto.Field(proto.MESSAGE, number=5, message="ThreatEntryAdditions",) - removals = proto.Field(proto.MESSAGE, number=6, message="ThreatEntryRemovals",) - - new_version_token = proto.Field(proto.BYTES, number=7) - + new_version_token = proto.Field(proto.BYTES, number=7,) checksum = proto.Field(proto.MESSAGE, number=8, message=Checksum,) - recommended_next_diff = proto.Field( - proto.MESSAGE, number=2, message=timestamp.Timestamp, + proto.MESSAGE, number=2, message=timestamp_pb2.Timestamp, ) class SearchUrisRequest(proto.Message): r"""Request to check URI entries against threatLists. - Attributes: uri (str): Required. The URI to be checked for matches. @@ -182,14 +165,12 @@ class SearchUrisRequest(proto.Message): Required. The ThreatLists to search in. """ - uri = proto.Field(proto.STRING, number=1) - + uri = proto.Field(proto.STRING, number=1,) threat_types = proto.RepeatedField(proto.ENUM, number=2, enum="ThreatType",) class SearchUrisResponse(proto.Message): r""" - Attributes: threat (google.cloud.webrisk_v1beta1.types.SearchUrisResponse.ThreatUri): The threat list matches. This may be empty if @@ -198,7 +179,6 @@ class SearchUrisResponse(proto.Message): class ThreatUri(proto.Message): r"""Contains threat information on a matching uri. - Attributes: threat_types (Sequence[google.cloud.webrisk_v1beta1.types.ThreatType]): The ThreatList this threat belongs to. @@ -209,8 +189,9 @@ class ThreatUri(proto.Message): """ threat_types = proto.RepeatedField(proto.ENUM, number=1, enum="ThreatType",) - - expire_time = proto.Field(proto.MESSAGE, number=2, message=timestamp.Timestamp,) + expire_time = proto.Field( + proto.MESSAGE, number=2, message=timestamp_pb2.Timestamp, + ) threat = proto.Field(proto.MESSAGE, number=1, message=ThreatUri,) @@ -228,14 +209,12 @@ class SearchHashesRequest(proto.Message): Required. The ThreatLists to search in. """ - hash_prefix = proto.Field(proto.BYTES, number=1) - + hash_prefix = proto.Field(proto.BYTES, number=1,) threat_types = proto.RepeatedField(proto.ENUM, number=2, enum="ThreatType",) class SearchHashesResponse(proto.Message): r""" - Attributes: threats (Sequence[google.cloud.webrisk_v1beta1.types.SearchHashesResponse.ThreatHash]): The full hashes that matched the requested @@ -248,7 +227,6 @@ class SearchHashesResponse(proto.Message): class ThreatHash(proto.Message): r"""Contains threat information on a matching hash. - Attributes: threat_types (Sequence[google.cloud.webrisk_v1beta1.types.ThreatType]): The ThreatList this threat belongs to. @@ -264,15 +242,14 @@ class ThreatHash(proto.Message): """ threat_types = proto.RepeatedField(proto.ENUM, number=1, enum="ThreatType",) - - hash_ = proto.Field(proto.BYTES, number=2) - - expire_time = proto.Field(proto.MESSAGE, number=3, message=timestamp.Timestamp,) + hash_ = proto.Field(proto.BYTES, number=2,) + expire_time = proto.Field( + proto.MESSAGE, number=3, message=timestamp_pb2.Timestamp, + ) threats = proto.RepeatedField(proto.MESSAGE, number=1, message=ThreatHash,) - negative_expire_time = proto.Field( - proto.MESSAGE, number=2, message=timestamp.Timestamp, + proto.MESSAGE, number=2, message=timestamp_pb2.Timestamp, ) @@ -294,13 +271,11 @@ class ThreatEntryAdditions(proto.Message): """ raw_hashes = proto.RepeatedField(proto.MESSAGE, number=1, message="RawHashes",) - rice_hashes = proto.Field(proto.MESSAGE, number=2, message="RiceDeltaEncoding",) class ThreatEntryRemovals(proto.Message): r"""Contains the set of entries to remove from a local database. - Attributes: raw_indices (google.cloud.webrisk_v1beta1.types.RawIndices): The raw removal indices for a local list. @@ -313,20 +288,18 @@ class ThreatEntryRemovals(proto.Message): """ raw_indices = proto.Field(proto.MESSAGE, number=1, message="RawIndices",) - rice_indices = proto.Field(proto.MESSAGE, number=2, message="RiceDeltaEncoding",) class RawIndices(proto.Message): r"""A set of raw indices to remove from a local list. - Attributes: indices (Sequence[int]): The indices to remove from a lexicographically-sorted local list. """ - indices = proto.RepeatedField(proto.INT32, number=1) + indices = proto.RepeatedField(proto.INT32, number=1,) class RawHashes(proto.Message): @@ -351,9 +324,8 @@ class RawHashes(proto.Message): are base64-encoded. """ - prefix_size = proto.Field(proto.INT32, number=1) - - raw_hashes = proto.Field(proto.BYTES, number=2) + prefix_size = proto.Field(proto.INT32, number=1,) + raw_hashes = proto.Field(proto.BYTES, number=2,) class RiceDeltaEncoding(proto.Message): @@ -379,13 +351,10 @@ class RiceDeltaEncoding(proto.Message): Golomb-Rice coder. """ - first_value = proto.Field(proto.INT64, number=1) - - rice_parameter = proto.Field(proto.INT32, number=2) - - entry_count = proto.Field(proto.INT32, number=3) - - encoded_data = proto.Field(proto.BYTES, number=4) + first_value = proto.Field(proto.INT64, number=1,) + rice_parameter = proto.Field(proto.INT32, number=2,) + entry_count = proto.Field(proto.INT32, number=3,) + encoded_data = proto.Field(proto.BYTES, number=4,) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/noxfile.py b/noxfile.py index af50a60..94ee6a8 100644 --- a/noxfile.py +++ b/noxfile.py @@ -62,16 +62,9 @@ def lint(session): session.run("flake8", "google", "tests") -@nox.session(python="3.6") +@nox.session(python=DEFAULT_PYTHON_VERSION) def blacken(session): - """Run black. - - Format code to uniform standard. - - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. - That run uses an image that doesn't have 3.6 installed. Before updating this - check the state of the `gcp_ubuntu_config` we use for that Kokoro run. - """ + """Run black. Format code to uniform standard.""" session.install(BLACK_VERSION) session.run( "black", *BLACK_PATHS, @@ -131,9 +124,6 @@ def system(session): # Check the value of `RUN_SYSTEM_TESTS` env var. It defaults to true. if os.environ.get("RUN_SYSTEM_TESTS", "true") == "false": session.skip("RUN_SYSTEM_TESTS is set to false, skipping") - # 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") @@ -189,7 +179,7 @@ def docs(session): """Build the docs for this library.""" session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark") + session.install("sphinx==4.0.1", "alabaster", "recommonmark") shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( @@ -211,7 +201,9 @@ def docfx(session): """Build the docfx yaml files for this library.""" session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml") + session.install( + "sphinx==4.0.1", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml" + ) shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( diff --git a/synth.py b/owlbot.py similarity index 84% rename from synth.py rename to owlbot.py index c662184..fa79b0c 100644 --- a/synth.py +++ b/owlbot.py @@ -17,22 +17,13 @@ import synthtool as s from synthtool import gcp -gapic = gcp.GAPICBazel() common = gcp.CommonTemplates() -versions = ["v1beta1", "v1"] - # ---------------------------------------------------------------------------- # Generate webrisk GAPIC layer # ---------------------------------------------------------------------------- -for version in versions: - library = gapic.py_library( - service="webrisk", - version=version, - bazel_target=f"//google/cloud/webrisk/{version}:webrisk-{version}-py", - include_protos=True, - ) +for library in s.get_staging_dirs("v1"): s.copy(library, excludes=["docs/index.rst", "nox.py", "README.rst", "setup.py"]) - +s.remove_staging_dirs() # ---------------------------------------------------------------------------- # Add templated files diff --git a/renovate.json b/renovate.json index f08bc22..c048955 100644 --- a/renovate.json +++ b/renovate.json @@ -2,5 +2,8 @@ "extends": [ "config:base", ":preserveSemverRanges" ], - "ignorePaths": [".pre-commit-config.yaml"] + "ignorePaths": [".pre-commit-config.yaml"], + "pip_requirements": { + "fileMatch": ["requirements-test.txt", "samples/[\\S/]*constraints.txt", "samples/[\\S/]*constraints-test.txt"] + } } diff --git a/scripts/fixup_webrisk_v1_keywords.py b/scripts/fixup_webrisk_v1_keywords.py index 12cef51..db9f1d3 100644 --- a/scripts/fixup_webrisk_v1_keywords.py +++ b/scripts/fixup_webrisk_v1_keywords.py @@ -1,6 +1,5 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import argparse import os import libcst as cst @@ -41,11 +39,10 @@ def partition( class webriskCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'compute_threat_list_diff': ('threat_type', 'constraints', 'version_token', ), - 'create_submission': ('parent', 'submission', ), - 'search_hashes': ('threat_types', 'hash_prefix', ), - 'search_uris': ('uri', 'threat_types', ), - + 'compute_threat_list_diff': ('threat_type', 'constraints', 'version_token', ), + 'create_submission': ('parent', 'submission', ), + 'search_hashes': ('threat_types', 'hash_prefix', ), + 'search_uris': ('uri', 'threat_types', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: @@ -76,7 +73,7 @@ def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: value=cst.Dict([ cst.DictElement( cst.SimpleString("'{}'".format(name)), - cst.Element(value=arg.value) +cst.Element(value=arg.value) ) # Note: the args + kwargs looks silly, but keep in mind that # the control parameters had to be stripped out, and that diff --git a/scripts/fixup_webrisk_v1beta1_keywords.py b/scripts/fixup_webrisk_v1beta1_keywords.py index bca0bc4..4b1391c 100644 --- a/scripts/fixup_webrisk_v1beta1_keywords.py +++ b/scripts/fixup_webrisk_v1beta1_keywords.py @@ -1,6 +1,5 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import argparse import os import libcst as cst @@ -41,10 +39,9 @@ def partition( class webriskCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'compute_threat_list_diff': ('threat_type', 'constraints', 'version_token', ), - 'search_hashes': ('threat_types', 'hash_prefix', ), - 'search_uris': ('uri', 'threat_types', ), - + 'compute_threat_list_diff': ('threat_type', 'constraints', 'version_token', ), + 'search_hashes': ('threat_types', 'hash_prefix', ), + 'search_uris': ('uri', 'threat_types', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: @@ -75,7 +72,7 @@ def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: value=cst.Dict([ cst.DictElement( cst.SimpleString("'{}'".format(name)), - cst.Element(value=arg.value) +cst.Element(value=arg.value) ) # Note: the args + kwargs looks silly, but keep in mind that # the control parameters had to be stripped out, and that diff --git a/setup.py b/setup.py index 5fc89ca..5718d0a 100644 --- a/setup.py +++ b/setup.py @@ -22,15 +22,16 @@ name = "google-cloud-webrisk" description = "Google Cloud Web Risk API client library" -version = "1.2.0" +version = "1.3.0" # Should be one of: # 'Development Status :: 3 - Alpha' # 'Development Status :: 4 - Beta' # 'Development Status :: 5 - Production/Stable' -release_status = "Development Status :: 3 - Alpha" +release_status = "Development Status :: 5 - Production/Stable" dependencies = [ "google-api-core[grpc] >= 1.22.2, < 2.0.0dev", "proto-plus >= 1.10.0", + "packaging >= 14.3", ] extras = {} diff --git a/synth.metadata b/synth.metadata deleted file mode 100644 index e7d4b13..0000000 --- a/synth.metadata +++ /dev/null @@ -1,163 +0,0 @@ -{ - "sources": [ - { - "git": { - "name": ".", - "remote": "https://github.com/googleapis/python-webrisk.git", - "sha": "c22255a70e3ba945f95f33a5c313faa15c1fb506" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "80c3d0da03afdb09a194341087fe666743d694a0", - "internalRef": "364697203" - } - }, - { - "git": { - "name": "synthtool", - "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4501974ad08b5d693311457e2ea4ce845676e329" - } - } - ], - "destinations": [ - { - "client": { - "source": "googleapis", - "apiName": "webrisk", - "apiVersion": "v1beta1", - "language": "python", - "generator": "bazel" - } - }, - { - "client": { - "source": "googleapis", - "apiName": "webrisk", - "apiVersion": "v1", - "language": "python", - "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/multiprocessing.rst", - "docs/webrisk_v1/services.rst", - "docs/webrisk_v1/types.rst", - "docs/webrisk_v1/web_risk_service.rst", - "docs/webrisk_v1beta1/services.rst", - "docs/webrisk_v1beta1/types.rst", - "docs/webrisk_v1beta1/web_risk_service_v1_beta1.rst", - "google/cloud/webrisk/__init__.py", - "google/cloud/webrisk/py.typed", - "google/cloud/webrisk_v1/__init__.py", - "google/cloud/webrisk_v1/proto/webrisk.proto", - "google/cloud/webrisk_v1/py.typed", - "google/cloud/webrisk_v1/services/__init__.py", - "google/cloud/webrisk_v1/services/web_risk_service/__init__.py", - "google/cloud/webrisk_v1/services/web_risk_service/async_client.py", - "google/cloud/webrisk_v1/services/web_risk_service/client.py", - "google/cloud/webrisk_v1/services/web_risk_service/transports/__init__.py", - "google/cloud/webrisk_v1/services/web_risk_service/transports/base.py", - "google/cloud/webrisk_v1/services/web_risk_service/transports/grpc.py", - "google/cloud/webrisk_v1/services/web_risk_service/transports/grpc_asyncio.py", - "google/cloud/webrisk_v1/types/__init__.py", - "google/cloud/webrisk_v1/types/webrisk.py", - "google/cloud/webrisk_v1beta1/__init__.py", - "google/cloud/webrisk_v1beta1/proto/webrisk.proto", - "google/cloud/webrisk_v1beta1/py.typed", - "google/cloud/webrisk_v1beta1/services/__init__.py", - "google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/__init__.py", - "google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/async_client.py", - "google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/client.py", - "google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/__init__.py", - "google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/base.py", - "google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc.py", - "google/cloud/webrisk_v1beta1/services/web_risk_service_v1_beta1/transports/grpc_asyncio.py", - "google/cloud/webrisk_v1beta1/types/__init__.py", - "google/cloud/webrisk_v1beta1/types/webrisk.py", - "mypy.ini", - "noxfile.py", - "renovate.json", - "samples/AUTHORING_GUIDE.md", - "samples/CONTRIBUTING.md", - "scripts/decrypt-secrets.sh", - "scripts/fixup_webrisk_v1_keywords.py", - "scripts/fixup_webrisk_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/webrisk_v1/__init__.py", - "tests/unit/gapic/webrisk_v1/test_web_risk_service.py", - "tests/unit/gapic/webrisk_v1beta1/__init__.py", - "tests/unit/gapic/webrisk_v1beta1/test_web_risk_service_v1_beta1.py", - "webrisk-v1-py.tar.gz" - ] -} \ No newline at end of file diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index 4595736..eb64cb3 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -6,4 +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-api-core==1.22.2 -proto-plus==1.10.0 \ No newline at end of file +proto-plus==1.10.0 +packaging==14.3 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,15 @@ +# -*- 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/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/tests/unit/__init__.py @@ -0,0 +1,15 @@ +# -*- 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/__init__.py b/tests/unit/gapic/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/tests/unit/gapic/__init__.py @@ -0,0 +1,15 @@ +# -*- 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/webrisk_v1/__init__.py b/tests/unit/gapic/webrisk_v1/__init__.py index 42ffdf2..4de6597 100644 --- a/tests/unit/gapic/webrisk_v1/__init__.py +++ b/tests/unit/gapic/webrisk_v1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/tests/unit/gapic/webrisk_v1/test_web_risk_service.py b/tests/unit/gapic/webrisk_v1/test_web_risk_service.py index 6a7bcdf..94defad 100644 --- a/tests/unit/gapic/webrisk_v1/test_web_risk_service.py +++ b/tests/unit/gapic/webrisk_v1/test_web_risk_service.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import os import mock +import packaging.version import grpc from grpc.experimental import aio @@ -24,20 +23,50 @@ import pytest from proto.marshal.rules.dates import DurationRule, TimestampRule -from google import auth + from google.api_core import client_options -from google.api_core import exceptions +from google.api_core import exceptions as core_exceptions from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.auth import credentials +from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.webrisk_v1.services.web_risk_service import WebRiskServiceAsyncClient from google.cloud.webrisk_v1.services.web_risk_service import WebRiskServiceClient from google.cloud.webrisk_v1.services.web_risk_service import transports +from google.cloud.webrisk_v1.services.web_risk_service.transports.base import ( + _API_CORE_VERSION, +) +from google.cloud.webrisk_v1.services.web_risk_service.transports.base import ( + _GOOGLE_AUTH_VERSION, +) from google.cloud.webrisk_v1.types import webrisk from google.oauth2 import service_account -from google.protobuf import timestamp_pb2 as timestamp # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +import google.auth + + +# TODO(busunkim): Once google-api-core >= 1.26.0 is required: +# - Delete all the api-core and auth "less than" test cases +# - Delete these pytest markers (Make the "greater than or equal to" tests the default). +requires_google_auth_lt_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), + reason="This test requires google-auth < 1.25.0", +) +requires_google_auth_gte_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), + reason="This test requires google-auth >= 1.25.0", +) + +requires_api_core_lt_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) >= packaging.version.parse("1.26.0"), + reason="This test requires google-api-core < 1.26.0", +) + +requires_api_core_gte_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) < packaging.version.parse("1.26.0"), + reason="This test requires google-api-core >= 1.26.0", +) def client_cert_source_callback(): @@ -88,7 +117,7 @@ def test__get_default_mtls_endpoint(): "client_class", [WebRiskServiceClient, WebRiskServiceAsyncClient,] ) def test_web_risk_service_client_from_service_account_info(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_info" ) as factory: @@ -105,7 +134,7 @@ def test_web_risk_service_client_from_service_account_info(client_class): "client_class", [WebRiskServiceClient, WebRiskServiceAsyncClient,] ) def test_web_risk_service_client_from_service_account_file(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_file" ) as factory: @@ -158,7 +187,7 @@ def test_web_risk_service_client_client_options( ): # Check that if channel is provided we won't create a new one. with mock.patch.object(WebRiskServiceClient, "get_transport_class") as gtc: - transport = transport_class(credentials=credentials.AnonymousCredentials()) + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) client = client_class(transport=transport) gtc.assert_not_called() @@ -446,7 +475,7 @@ def test_compute_threat_list_diff( transport: str = "grpc", request_type=webrisk.ComputeThreatListDiffRequest ): client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -462,24 +491,19 @@ def test_compute_threat_list_diff( response_type=webrisk.ComputeThreatListDiffResponse.ResponseType.DIFF, new_version_token=b"new_version_token_blob", ) - response = client.compute_threat_list_diff(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.ComputeThreatListDiffRequest() # Establish that the response is the type that we expect. - assert isinstance(response, webrisk.ComputeThreatListDiffResponse) - assert ( response.response_type == webrisk.ComputeThreatListDiffResponse.ResponseType.DIFF ) - assert response.new_version_token == b"new_version_token_blob" @@ -491,7 +515,7 @@ def test_compute_threat_list_diff_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 = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -501,7 +525,6 @@ def test_compute_threat_list_diff_empty_call(): client.compute_threat_list_diff() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.ComputeThreatListDiffRequest() @@ -510,7 +533,7 @@ async def test_compute_threat_list_diff_async( transport: str = "grpc_asyncio", request_type=webrisk.ComputeThreatListDiffRequest ): client = WebRiskServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -528,23 +551,19 @@ async def test_compute_threat_list_diff_async( new_version_token=b"new_version_token_blob", ) ) - response = await client.compute_threat_list_diff(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.ComputeThreatListDiffRequest() # Establish that the response is the type that we expect. assert isinstance(response, webrisk.ComputeThreatListDiffResponse) - assert ( response.response_type == webrisk.ComputeThreatListDiffResponse.ResponseType.DIFF ) - assert response.new_version_token == b"new_version_token_blob" @@ -554,7 +573,7 @@ async def test_compute_threat_list_diff_async_from_dict(): def test_compute_threat_list_diff_flattened(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -562,7 +581,6 @@ def test_compute_threat_list_diff_flattened(): ) as call: # Designate an appropriate return value for the call. call.return_value = webrisk.ComputeThreatListDiffResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.compute_threat_list_diff( @@ -577,18 +595,15 @@ def test_compute_threat_list_diff_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].threat_type == webrisk.ThreatType.MALWARE - assert args[0].version_token == b"version_token_blob" - assert args[0].constraints == webrisk.ComputeThreatListDiffRequest.Constraints( max_diff_entries=1687 ) def test_compute_threat_list_diff_flattened_error(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -605,7 +620,9 @@ def test_compute_threat_list_diff_flattened_error(): @pytest.mark.asyncio async def test_compute_threat_list_diff_flattened_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -631,11 +648,8 @@ async def test_compute_threat_list_diff_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].threat_type == webrisk.ThreatType.MALWARE - assert args[0].version_token == b"version_token_blob" - assert args[0].constraints == webrisk.ComputeThreatListDiffRequest.Constraints( max_diff_entries=1687 ) @@ -643,7 +657,9 @@ async def test_compute_threat_list_diff_flattened_async(): @pytest.mark.asyncio async def test_compute_threat_list_diff_flattened_error_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -660,7 +676,7 @@ async def test_compute_threat_list_diff_flattened_error_async(): def test_search_uris(transport: str = "grpc", request_type=webrisk.SearchUrisRequest): client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -671,17 +687,14 @@ def test_search_uris(transport: str = "grpc", request_type=webrisk.SearchUrisReq with mock.patch.object(type(client.transport.search_uris), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchUrisResponse() - response = client.search_uris(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchUrisRequest() # Establish that the response is the type that we expect. - assert isinstance(response, webrisk.SearchUrisResponse) @@ -693,7 +706,7 @@ def test_search_uris_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 = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -701,7 +714,6 @@ def test_search_uris_empty_call(): client.search_uris() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchUrisRequest() @@ -710,7 +722,7 @@ async def test_search_uris_async( transport: str = "grpc_asyncio", request_type=webrisk.SearchUrisRequest ): client = WebRiskServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -723,13 +735,11 @@ async def test_search_uris_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( webrisk.SearchUrisResponse() ) - response = await client.search_uris(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchUrisRequest() # Establish that the response is the type that we expect. @@ -742,13 +752,12 @@ async def test_search_uris_async_from_dict(): def test_search_uris_flattened(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.search_uris), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchUrisResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.search_uris( @@ -759,14 +768,12 @@ def test_search_uris_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].uri == "uri_value" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] def test_search_uris_flattened_error(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -780,7 +787,9 @@ def test_search_uris_flattened_error(): @pytest.mark.asyncio async def test_search_uris_flattened_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.search_uris), "__call__") as call: @@ -800,15 +809,15 @@ async def test_search_uris_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].uri == "uri_value" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] @pytest.mark.asyncio async def test_search_uris_flattened_error_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -824,7 +833,7 @@ def test_search_hashes( transport: str = "grpc", request_type=webrisk.SearchHashesRequest ): client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -835,17 +844,14 @@ def test_search_hashes( with mock.patch.object(type(client.transport.search_hashes), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchHashesResponse() - response = client.search_hashes(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchHashesRequest() # Establish that the response is the type that we expect. - assert isinstance(response, webrisk.SearchHashesResponse) @@ -857,7 +863,7 @@ def test_search_hashes_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 = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -865,7 +871,6 @@ def test_search_hashes_empty_call(): client.search_hashes() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchHashesRequest() @@ -874,7 +879,7 @@ async def test_search_hashes_async( transport: str = "grpc_asyncio", request_type=webrisk.SearchHashesRequest ): client = WebRiskServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -887,13 +892,11 @@ async def test_search_hashes_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( webrisk.SearchHashesResponse() ) - response = await client.search_hashes(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchHashesRequest() # Establish that the response is the type that we expect. @@ -906,13 +909,12 @@ async def test_search_hashes_async_from_dict(): def test_search_hashes_flattened(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.search_hashes), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchHashesResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.search_hashes( @@ -923,14 +925,12 @@ def test_search_hashes_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].hash_prefix == b"hash_prefix_blob" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] def test_search_hashes_flattened_error(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -944,7 +944,9 @@ def test_search_hashes_flattened_error(): @pytest.mark.asyncio async def test_search_hashes_flattened_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.search_hashes), "__call__") as call: @@ -964,15 +966,15 @@ async def test_search_hashes_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].hash_prefix == b"hash_prefix_blob" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] @pytest.mark.asyncio async def test_search_hashes_flattened_error_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -988,7 +990,7 @@ def test_create_submission( transport: str = "grpc", request_type=webrisk.CreateSubmissionRequest ): client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1001,19 +1003,15 @@ def test_create_submission( ) as call: # Designate an appropriate return value for the call. call.return_value = webrisk.Submission(uri="uri_value",) - response = client.create_submission(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.CreateSubmissionRequest() # Establish that the response is the type that we expect. - assert isinstance(response, webrisk.Submission) - assert response.uri == "uri_value" @@ -1025,7 +1023,7 @@ def test_create_submission_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 = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1035,7 +1033,6 @@ def test_create_submission_empty_call(): client.create_submission() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.CreateSubmissionRequest() @@ -1044,7 +1041,7 @@ async def test_create_submission_async( transport: str = "grpc_asyncio", request_type=webrisk.CreateSubmissionRequest ): client = WebRiskServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1059,18 +1056,15 @@ async def test_create_submission_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( webrisk.Submission(uri="uri_value",) ) - response = await client.create_submission(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.CreateSubmissionRequest() # Establish that the response is the type that we expect. assert isinstance(response, webrisk.Submission) - assert response.uri == "uri_value" @@ -1080,11 +1074,12 @@ async def test_create_submission_async_from_dict(): def test_create_submission_field_headers(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. request = webrisk.CreateSubmissionRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. @@ -1092,7 +1087,6 @@ def test_create_submission_field_headers(): type(client.transport.create_submission), "__call__" ) as call: call.return_value = webrisk.Submission() - client.create_submission(request) # Establish that the underlying gRPC stub method was called. @@ -1107,11 +1101,14 @@ def test_create_submission_field_headers(): @pytest.mark.asyncio async def test_create_submission_field_headers_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. request = webrisk.CreateSubmissionRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. @@ -1119,7 +1116,6 @@ async def test_create_submission_field_headers_async(): type(client.transport.create_submission), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(webrisk.Submission()) - await client.create_submission(request) # Establish that the underlying gRPC stub method was called. @@ -1133,7 +1129,7 @@ async def test_create_submission_field_headers_async(): def test_create_submission_flattened(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -1141,7 +1137,6 @@ def test_create_submission_flattened(): ) as call: # Designate an appropriate return value for the call. call.return_value = webrisk.Submission() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.create_submission( @@ -1152,14 +1147,12 @@ def test_create_submission_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].submission == webrisk.Submission(uri="uri_value") def test_create_submission_flattened_error(): - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1173,7 +1166,9 @@ def test_create_submission_flattened_error(): @pytest.mark.asyncio async def test_create_submission_flattened_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -1193,15 +1188,15 @@ async def test_create_submission_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].submission == webrisk.Submission(uri="uri_value") @pytest.mark.asyncio async def test_create_submission_flattened_error_async(): - client = WebRiskServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1216,16 +1211,16 @@ async def test_create_submission_flattened_error_async(): def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.WebRiskServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # It is an error to provide a credentials file and a transport instance. transport = transports.WebRiskServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = WebRiskServiceClient( @@ -1235,7 +1230,7 @@ def test_credentials_transport_error(): # It is an error to provide scopes and a transport instance. transport = transports.WebRiskServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = WebRiskServiceClient( @@ -1246,7 +1241,7 @@ def test_credentials_transport_error(): def test_transport_instance(): # A client may be instantiated with a custom transport instance. transport = transports.WebRiskServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) client = WebRiskServiceClient(transport=transport) assert client.transport is transport @@ -1255,13 +1250,13 @@ def test_transport_instance(): def test_transport_get_channel(): # A client may be instantiated with a custom transport instance. transport = transports.WebRiskServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel transport = transports.WebRiskServiceGrpcAsyncIOTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel @@ -1276,23 +1271,23 @@ def test_transport_get_channel(): ) def test_transport_adc(transport_class): # Test default credentials are used if not provided. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport_class() adc.assert_called_once() def test_transport_grpc_default(): # A client should use the gRPC transport by default. - client = WebRiskServiceClient(credentials=credentials.AnonymousCredentials(),) + client = WebRiskServiceClient(credentials=ga_credentials.AnonymousCredentials(),) assert isinstance(client.transport, transports.WebRiskServiceGrpcTransport,) def test_web_risk_service_base_transport_error(): # Passing both a credentials object and credentials_file should raise an error - with pytest.raises(exceptions.DuplicateCredentialArgs): + with pytest.raises(core_exceptions.DuplicateCredentialArgs): transport = transports.WebRiskServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), credentials_file="credentials.json", ) @@ -1304,7 +1299,7 @@ def test_web_risk_service_base_transport(): ) as Transport: Transport.return_value = None transport = transports.WebRiskServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Every method on the transport should just blindly @@ -1320,15 +1315,37 @@ def test_web_risk_service_base_transport(): getattr(transport, method)(request=object()) +@requires_google_auth_gte_1_25_0 def test_web_risk_service_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( - auth, "load_credentials_from_file" + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.webrisk_v1.services.web_risk_service.transports.WebRiskServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.WebRiskServiceTransport( + credentials_file="credentials.json", quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@requires_google_auth_lt_1_25_0 +def test_web_risk_service_base_transport_with_credentials_file_old_google_auth(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True ) as load_creds, mock.patch( "google.cloud.webrisk_v1.services.web_risk_service.transports.WebRiskServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - load_creds.return_value = (credentials.AnonymousCredentials(), None) + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.WebRiskServiceTransport( credentials_file="credentials.json", quota_project_id="octopus", ) @@ -1341,19 +1358,33 @@ def test_web_risk_service_base_transport_with_credentials_file(): def test_web_risk_service_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. - with mock.patch.object(auth, "default") as adc, mock.patch( + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( "google.cloud.webrisk_v1.services.web_risk_service.transports.WebRiskServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - adc.return_value = (credentials.AnonymousCredentials(), None) + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.WebRiskServiceTransport() adc.assert_called_once() +@requires_google_auth_gte_1_25_0 def test_web_risk_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + WebRiskServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@requires_google_auth_lt_1_25_0 +def test_web_risk_service_auth_adc_old_google_auth(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) WebRiskServiceClient() adc.assert_called_once_with( scopes=("https://www.googleapis.com/auth/cloud-platform",), @@ -1361,20 +1392,156 @@ def test_web_risk_service_auth_adc(): ) -def test_web_risk_service_transport_auth_adc(): +@pytest.mark.parametrize( + "transport_class", + [ + transports.WebRiskServiceGrpcTransport, + transports.WebRiskServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_gte_1_25_0 +def test_web_risk_service_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) - transports.WebRiskServiceGrpcTransport( - host="squid.clam.whelk", quota_project_id="octopus" + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.WebRiskServiceGrpcTransport, + transports.WebRiskServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_lt_1_25_0 +def test_web_risk_service_transport_auth_adc_old_google_auth(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus") adc.assert_called_once_with( scopes=("https://www.googleapis.com/auth/cloud-platform",), quota_project_id="octopus", ) +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.WebRiskServiceGrpcTransport, grpc_helpers), + (transports.WebRiskServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_gte_1_26_0 +def test_web_risk_service_transport_create_channel(transport_class, grpc_helpers): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "webrisk.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="webrisk.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.WebRiskServiceGrpcTransport, grpc_helpers), + (transports.WebRiskServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_web_risk_service_transport_create_channel_old_api_core( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus") + + create_channel.assert_called_with( + "webrisk.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.WebRiskServiceGrpcTransport, grpc_helpers), + (transports.WebRiskServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_web_risk_service_transport_create_channel_user_scopes( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "webrisk.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=["1", "2"], + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + @pytest.mark.parametrize( "transport_class", [ @@ -1383,7 +1550,7 @@ def test_web_risk_service_transport_auth_adc(): ], ) def test_web_risk_service_grpc_transport_client_cert_source_for_mtls(transport_class): - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() # Check ssl_channel_credentials is used if provided. with mock.patch.object(transport_class, "create_channel") as mock_create_channel: @@ -1422,7 +1589,7 @@ def test_web_risk_service_grpc_transport_client_cert_source_for_mtls(transport_c def test_web_risk_service_host_no_port(): client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="webrisk.googleapis.com" ), @@ -1432,7 +1599,7 @@ def test_web_risk_service_host_no_port(): def test_web_risk_service_host_with_port(): client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="webrisk.googleapis.com:8000" ), @@ -1488,9 +1655,9 @@ def test_web_risk_service_transport_channel_mtls_with_client_cert_source( mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() with pytest.warns(DeprecationWarning): - with mock.patch.object(auth, "default") as adc: + with mock.patch.object(google.auth, "default") as adc: adc.return_value = (cred, None) transport = transport_class( host="squid.clam.whelk", @@ -1566,7 +1733,6 @@ def test_web_risk_service_transport_channel_mtls_with_adc(transport_class): def test_common_billing_account_path(): billing_account = "squid" - expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -1587,7 +1753,6 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): folder = "whelk" - expected = "folders/{folder}".format(folder=folder,) actual = WebRiskServiceClient.common_folder_path(folder) assert expected == actual @@ -1606,7 +1771,6 @@ def test_parse_common_folder_path(): def test_common_organization_path(): organization = "oyster" - expected = "organizations/{organization}".format(organization=organization,) actual = WebRiskServiceClient.common_organization_path(organization) assert expected == actual @@ -1625,7 +1789,6 @@ def test_parse_common_organization_path(): def test_common_project_path(): project = "cuttlefish" - expected = "projects/{project}".format(project=project,) actual = WebRiskServiceClient.common_project_path(project) assert expected == actual @@ -1645,7 +1808,6 @@ def test_parse_common_project_path(): def test_common_location_path(): project = "winkle" location = "nautilus" - expected = "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -1672,7 +1834,7 @@ def test_client_withDEFAULT_CLIENT_INFO(): transports.WebRiskServiceTransport, "_prep_wrapped_messages" ) as prep: client = WebRiskServiceClient( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) @@ -1681,6 +1843,6 @@ def test_client_withDEFAULT_CLIENT_INFO(): ) as prep: transport_class = WebRiskServiceClient.get_transport_class() transport = transport_class( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/webrisk_v1beta1/__init__.py b/tests/unit/gapic/webrisk_v1beta1/__init__.py index 42ffdf2..4de6597 100644 --- a/tests/unit/gapic/webrisk_v1beta1/__init__.py +++ b/tests/unit/gapic/webrisk_v1beta1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/tests/unit/gapic/webrisk_v1beta1/test_web_risk_service_v1_beta1.py b/tests/unit/gapic/webrisk_v1beta1/test_web_risk_service_v1_beta1.py index 3d57d0f..33cf63b 100644 --- a/tests/unit/gapic/webrisk_v1beta1/test_web_risk_service_v1_beta1.py +++ b/tests/unit/gapic/webrisk_v1beta1/test_web_risk_service_v1_beta1.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import os import mock +import packaging.version import grpc from grpc.experimental import aio @@ -24,13 +23,13 @@ import pytest from proto.marshal.rules.dates import DurationRule, TimestampRule -from google import auth + from google.api_core import client_options -from google.api_core import exceptions +from google.api_core import exceptions as core_exceptions from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.auth import credentials +from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.webrisk_v1beta1.services.web_risk_service_v1_beta1 import ( WebRiskServiceV1Beta1AsyncClient, @@ -39,9 +38,39 @@ WebRiskServiceV1Beta1Client, ) from google.cloud.webrisk_v1beta1.services.web_risk_service_v1_beta1 import transports +from google.cloud.webrisk_v1beta1.services.web_risk_service_v1_beta1.transports.base import ( + _API_CORE_VERSION, +) +from google.cloud.webrisk_v1beta1.services.web_risk_service_v1_beta1.transports.base import ( + _GOOGLE_AUTH_VERSION, +) from google.cloud.webrisk_v1beta1.types import webrisk from google.oauth2 import service_account -from google.protobuf import timestamp_pb2 as timestamp # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +import google.auth + + +# TODO(busunkim): Once google-api-core >= 1.26.0 is required: +# - Delete all the api-core and auth "less than" test cases +# - Delete these pytest markers (Make the "greater than or equal to" tests the default). +requires_google_auth_lt_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), + reason="This test requires google-auth < 1.25.0", +) +requires_google_auth_gte_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), + reason="This test requires google-auth >= 1.25.0", +) + +requires_api_core_lt_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) >= packaging.version.parse("1.26.0"), + reason="This test requires google-api-core < 1.26.0", +) + +requires_api_core_gte_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) < packaging.version.parse("1.26.0"), + reason="This test requires google-api-core >= 1.26.0", +) def client_cert_source_callback(): @@ -93,7 +122,7 @@ def test__get_default_mtls_endpoint(): "client_class", [WebRiskServiceV1Beta1Client, WebRiskServiceV1Beta1AsyncClient,] ) def test_web_risk_service_v1_beta1_client_from_service_account_info(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_info" ) as factory: @@ -110,7 +139,7 @@ def test_web_risk_service_v1_beta1_client_from_service_account_info(client_class "client_class", [WebRiskServiceV1Beta1Client, WebRiskServiceV1Beta1AsyncClient,] ) def test_web_risk_service_v1_beta1_client_from_service_account_file(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_file" ) as factory: @@ -167,7 +196,7 @@ def test_web_risk_service_v1_beta1_client_client_options( ): # Check that if channel is provided we won't create a new one. with mock.patch.object(WebRiskServiceV1Beta1Client, "get_transport_class") as gtc: - transport = transport_class(credentials=credentials.AnonymousCredentials()) + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) client = client_class(transport=transport) gtc.assert_not_called() @@ -473,7 +502,7 @@ def test_compute_threat_list_diff( transport: str = "grpc", request_type=webrisk.ComputeThreatListDiffRequest ): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -489,24 +518,19 @@ def test_compute_threat_list_diff( response_type=webrisk.ComputeThreatListDiffResponse.ResponseType.DIFF, new_version_token=b"new_version_token_blob", ) - response = client.compute_threat_list_diff(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.ComputeThreatListDiffRequest() # Establish that the response is the type that we expect. - assert isinstance(response, webrisk.ComputeThreatListDiffResponse) - assert ( response.response_type == webrisk.ComputeThreatListDiffResponse.ResponseType.DIFF ) - assert response.new_version_token == b"new_version_token_blob" @@ -518,7 +542,7 @@ def test_compute_threat_list_diff_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 = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -528,7 +552,6 @@ def test_compute_threat_list_diff_empty_call(): client.compute_threat_list_diff() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.ComputeThreatListDiffRequest() @@ -537,7 +560,7 @@ async def test_compute_threat_list_diff_async( transport: str = "grpc_asyncio", request_type=webrisk.ComputeThreatListDiffRequest ): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -555,23 +578,19 @@ async def test_compute_threat_list_diff_async( new_version_token=b"new_version_token_blob", ) ) - response = await client.compute_threat_list_diff(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.ComputeThreatListDiffRequest() # Establish that the response is the type that we expect. assert isinstance(response, webrisk.ComputeThreatListDiffResponse) - assert ( response.response_type == webrisk.ComputeThreatListDiffResponse.ResponseType.DIFF ) - assert response.new_version_token == b"new_version_token_blob" @@ -582,7 +601,7 @@ async def test_compute_threat_list_diff_async_from_dict(): def test_compute_threat_list_diff_flattened(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -591,7 +610,6 @@ def test_compute_threat_list_diff_flattened(): ) as call: # Designate an appropriate return value for the call. call.return_value = webrisk.ComputeThreatListDiffResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.compute_threat_list_diff( @@ -606,11 +624,8 @@ def test_compute_threat_list_diff_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].threat_type == webrisk.ThreatType.MALWARE - assert args[0].version_token == b"version_token_blob" - assert args[0].constraints == webrisk.ComputeThreatListDiffRequest.Constraints( max_diff_entries=1687 ) @@ -618,7 +633,7 @@ def test_compute_threat_list_diff_flattened(): def test_compute_threat_list_diff_flattened_error(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Attempting to call a method with both a request object and flattened @@ -637,7 +652,7 @@ def test_compute_threat_list_diff_flattened_error(): @pytest.mark.asyncio async def test_compute_threat_list_diff_flattened_async(): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -664,11 +679,8 @@ async def test_compute_threat_list_diff_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].threat_type == webrisk.ThreatType.MALWARE - assert args[0].version_token == b"version_token_blob" - assert args[0].constraints == webrisk.ComputeThreatListDiffRequest.Constraints( max_diff_entries=1687 ) @@ -677,7 +689,7 @@ async def test_compute_threat_list_diff_flattened_async(): @pytest.mark.asyncio async def test_compute_threat_list_diff_flattened_error_async(): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Attempting to call a method with both a request object and flattened @@ -695,7 +707,7 @@ async def test_compute_threat_list_diff_flattened_error_async(): def test_search_uris(transport: str = "grpc", request_type=webrisk.SearchUrisRequest): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -706,17 +718,14 @@ def test_search_uris(transport: str = "grpc", request_type=webrisk.SearchUrisReq with mock.patch.object(type(client.transport.search_uris), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchUrisResponse() - response = client.search_uris(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchUrisRequest() # Establish that the response is the type that we expect. - assert isinstance(response, webrisk.SearchUrisResponse) @@ -728,7 +737,7 @@ def test_search_uris_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 = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -736,7 +745,6 @@ def test_search_uris_empty_call(): client.search_uris() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchUrisRequest() @@ -745,7 +753,7 @@ async def test_search_uris_async( transport: str = "grpc_asyncio", request_type=webrisk.SearchUrisRequest ): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -758,13 +766,11 @@ async def test_search_uris_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( webrisk.SearchUrisResponse() ) - response = await client.search_uris(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchUrisRequest() # Establish that the response is the type that we expect. @@ -778,14 +784,13 @@ async def test_search_uris_async_from_dict(): def test_search_uris_flattened(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.search_uris), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchUrisResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.search_uris( @@ -796,15 +801,13 @@ def test_search_uris_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].uri == "uri_value" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] def test_search_uris_flattened_error(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Attempting to call a method with both a request object and flattened @@ -820,7 +823,7 @@ def test_search_uris_flattened_error(): @pytest.mark.asyncio async def test_search_uris_flattened_async(): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -841,16 +844,14 @@ async def test_search_uris_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].uri == "uri_value" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] @pytest.mark.asyncio async def test_search_uris_flattened_error_async(): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Attempting to call a method with both a request object and flattened @@ -867,7 +868,7 @@ def test_search_hashes( transport: str = "grpc", request_type=webrisk.SearchHashesRequest ): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -878,17 +879,14 @@ def test_search_hashes( with mock.patch.object(type(client.transport.search_hashes), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchHashesResponse() - response = client.search_hashes(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchHashesRequest() # Establish that the response is the type that we expect. - assert isinstance(response, webrisk.SearchHashesResponse) @@ -900,7 +898,7 @@ def test_search_hashes_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 = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -908,7 +906,6 @@ def test_search_hashes_empty_call(): client.search_hashes() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchHashesRequest() @@ -917,7 +914,7 @@ async def test_search_hashes_async( transport: str = "grpc_asyncio", request_type=webrisk.SearchHashesRequest ): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -930,13 +927,11 @@ async def test_search_hashes_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( webrisk.SearchHashesResponse() ) - response = await client.search_hashes(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == webrisk.SearchHashesRequest() # Establish that the response is the type that we expect. @@ -950,14 +945,13 @@ async def test_search_hashes_async_from_dict(): def test_search_hashes_flattened(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.search_hashes), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = webrisk.SearchHashesResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.search_hashes( @@ -968,15 +962,13 @@ def test_search_hashes_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].hash_prefix == b"hash_prefix_blob" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] def test_search_hashes_flattened_error(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Attempting to call a method with both a request object and flattened @@ -992,7 +984,7 @@ def test_search_hashes_flattened_error(): @pytest.mark.asyncio async def test_search_hashes_flattened_async(): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1013,16 +1005,14 @@ async def test_search_hashes_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].hash_prefix == b"hash_prefix_blob" - assert args[0].threat_types == [webrisk.ThreatType.MALWARE] @pytest.mark.asyncio async def test_search_hashes_flattened_error_async(): client = WebRiskServiceV1Beta1AsyncClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Attempting to call a method with both a request object and flattened @@ -1038,16 +1028,16 @@ async def test_search_hashes_flattened_error_async(): def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.WebRiskServiceV1Beta1GrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # It is an error to provide a credentials file and a transport instance. transport = transports.WebRiskServiceV1Beta1GrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = WebRiskServiceV1Beta1Client( @@ -1057,7 +1047,7 @@ def test_credentials_transport_error(): # It is an error to provide scopes and a transport instance. transport = transports.WebRiskServiceV1Beta1GrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = WebRiskServiceV1Beta1Client( @@ -1068,7 +1058,7 @@ def test_credentials_transport_error(): def test_transport_instance(): # A client may be instantiated with a custom transport instance. transport = transports.WebRiskServiceV1Beta1GrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) client = WebRiskServiceV1Beta1Client(transport=transport) assert client.transport is transport @@ -1077,13 +1067,13 @@ def test_transport_instance(): def test_transport_get_channel(): # A client may be instantiated with a custom transport instance. transport = transports.WebRiskServiceV1Beta1GrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel transport = transports.WebRiskServiceV1Beta1GrpcAsyncIOTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel @@ -1098,8 +1088,8 @@ def test_transport_get_channel(): ) def test_transport_adc(transport_class): # Test default credentials are used if not provided. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport_class() adc.assert_called_once() @@ -1107,16 +1097,16 @@ def test_transport_adc(transport_class): def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) assert isinstance(client.transport, transports.WebRiskServiceV1Beta1GrpcTransport,) def test_web_risk_service_v1_beta1_base_transport_error(): # Passing both a credentials object and credentials_file should raise an error - with pytest.raises(exceptions.DuplicateCredentialArgs): + with pytest.raises(core_exceptions.DuplicateCredentialArgs): transport = transports.WebRiskServiceV1Beta1Transport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), credentials_file="credentials.json", ) @@ -1128,7 +1118,7 @@ def test_web_risk_service_v1_beta1_base_transport(): ) as Transport: Transport.return_value = None transport = transports.WebRiskServiceV1Beta1Transport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Every method on the transport should just blindly @@ -1143,15 +1133,37 @@ def test_web_risk_service_v1_beta1_base_transport(): getattr(transport, method)(request=object()) +@requires_google_auth_gte_1_25_0 def test_web_risk_service_v1_beta1_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( - auth, "load_credentials_from_file" + google.auth, "load_credentials_from_file", autospec=True ) as load_creds, mock.patch( "google.cloud.webrisk_v1beta1.services.web_risk_service_v1_beta1.transports.WebRiskServiceV1Beta1Transport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - load_creds.return_value = (credentials.AnonymousCredentials(), None) + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.WebRiskServiceV1Beta1Transport( + credentials_file="credentials.json", quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@requires_google_auth_lt_1_25_0 +def test_web_risk_service_v1_beta1_base_transport_with_credentials_file_old_google_auth(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.webrisk_v1beta1.services.web_risk_service_v1_beta1.transports.WebRiskServiceV1Beta1Transport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.WebRiskServiceV1Beta1Transport( credentials_file="credentials.json", quota_project_id="octopus", ) @@ -1164,19 +1176,33 @@ def test_web_risk_service_v1_beta1_base_transport_with_credentials_file(): def test_web_risk_service_v1_beta1_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. - with mock.patch.object(auth, "default") as adc, mock.patch( + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( "google.cloud.webrisk_v1beta1.services.web_risk_service_v1_beta1.transports.WebRiskServiceV1Beta1Transport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - adc.return_value = (credentials.AnonymousCredentials(), None) + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.WebRiskServiceV1Beta1Transport() adc.assert_called_once() +@requires_google_auth_gte_1_25_0 def test_web_risk_service_v1_beta1_auth_adc(): # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + WebRiskServiceV1Beta1Client() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@requires_google_auth_lt_1_25_0 +def test_web_risk_service_v1_beta1_auth_adc_old_google_auth(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) WebRiskServiceV1Beta1Client() adc.assert_called_once_with( scopes=("https://www.googleapis.com/auth/cloud-platform",), @@ -1184,20 +1210,158 @@ def test_web_risk_service_v1_beta1_auth_adc(): ) -def test_web_risk_service_v1_beta1_transport_auth_adc(): +@pytest.mark.parametrize( + "transport_class", + [ + transports.WebRiskServiceV1Beta1GrpcTransport, + transports.WebRiskServiceV1Beta1GrpcAsyncIOTransport, + ], +) +@requires_google_auth_gte_1_25_0 +def test_web_risk_service_v1_beta1_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) - transports.WebRiskServiceV1Beta1GrpcTransport( - host="squid.clam.whelk", quota_project_id="octopus" + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.WebRiskServiceV1Beta1GrpcTransport, + transports.WebRiskServiceV1Beta1GrpcAsyncIOTransport, + ], +) +@requires_google_auth_lt_1_25_0 +def test_web_risk_service_v1_beta1_transport_auth_adc_old_google_auth(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus") adc.assert_called_once_with( scopes=("https://www.googleapis.com/auth/cloud-platform",), quota_project_id="octopus", ) +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.WebRiskServiceV1Beta1GrpcTransport, grpc_helpers), + (transports.WebRiskServiceV1Beta1GrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_gte_1_26_0 +def test_web_risk_service_v1_beta1_transport_create_channel( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "webrisk.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="webrisk.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.WebRiskServiceV1Beta1GrpcTransport, grpc_helpers), + (transports.WebRiskServiceV1Beta1GrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_web_risk_service_v1_beta1_transport_create_channel_old_api_core( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus") + + create_channel.assert_called_with( + "webrisk.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.WebRiskServiceV1Beta1GrpcTransport, grpc_helpers), + (transports.WebRiskServiceV1Beta1GrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_web_risk_service_v1_beta1_transport_create_channel_user_scopes( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "webrisk.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=["1", "2"], + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + @pytest.mark.parametrize( "transport_class", [ @@ -1208,7 +1372,7 @@ def test_web_risk_service_v1_beta1_transport_auth_adc(): def test_web_risk_service_v1_beta1_grpc_transport_client_cert_source_for_mtls( transport_class, ): - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() # Check ssl_channel_credentials is used if provided. with mock.patch.object(transport_class, "create_channel") as mock_create_channel: @@ -1247,7 +1411,7 @@ def test_web_risk_service_v1_beta1_grpc_transport_client_cert_source_for_mtls( def test_web_risk_service_v1_beta1_host_no_port(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="webrisk.googleapis.com" ), @@ -1257,7 +1421,7 @@ def test_web_risk_service_v1_beta1_host_no_port(): def test_web_risk_service_v1_beta1_host_with_port(): client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="webrisk.googleapis.com:8000" ), @@ -1313,9 +1477,9 @@ def test_web_risk_service_v1_beta1_transport_channel_mtls_with_client_cert_sourc mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() with pytest.warns(DeprecationWarning): - with mock.patch.object(auth, "default") as adc: + with mock.patch.object(google.auth, "default") as adc: adc.return_value = (cred, None) transport = transport_class( host="squid.clam.whelk", @@ -1391,7 +1555,6 @@ def test_web_risk_service_v1_beta1_transport_channel_mtls_with_adc(transport_cla def test_common_billing_account_path(): billing_account = "squid" - expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -1412,7 +1575,6 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): folder = "whelk" - expected = "folders/{folder}".format(folder=folder,) actual = WebRiskServiceV1Beta1Client.common_folder_path(folder) assert expected == actual @@ -1431,7 +1593,6 @@ def test_parse_common_folder_path(): def test_common_organization_path(): organization = "oyster" - expected = "organizations/{organization}".format(organization=organization,) actual = WebRiskServiceV1Beta1Client.common_organization_path(organization) assert expected == actual @@ -1450,7 +1611,6 @@ def test_parse_common_organization_path(): def test_common_project_path(): project = "cuttlefish" - expected = "projects/{project}".format(project=project,) actual = WebRiskServiceV1Beta1Client.common_project_path(project) assert expected == actual @@ -1470,7 +1630,6 @@ def test_parse_common_project_path(): def test_common_location_path(): project = "winkle" location = "nautilus" - expected = "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -1497,7 +1656,7 @@ def test_client_withDEFAULT_CLIENT_INFO(): transports.WebRiskServiceV1Beta1Transport, "_prep_wrapped_messages" ) as prep: client = WebRiskServiceV1Beta1Client( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) @@ -1506,6 +1665,6 @@ def test_client_withDEFAULT_CLIENT_INFO(): ) as prep: transport_class = WebRiskServiceV1Beta1Client.get_transport_class() transport = transport_class( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) diff --git a/webrisk-v1-py.tar.gz b/webrisk-v1-py.tar.gz deleted file mode 100644 index e69de29..0000000