diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 7d98291c..eecb84c2 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:58f73ba196b5414782605236dd0712a73541b44ff2ff4d3a36ec41092dd6fa5b + digest: sha256:ae600f36b6bc972b368367b6f83a1d91ec2c82a4a116b383d67d547c56fe6de3 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ac72fed3..62aced93 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,9 +3,10 @@ # # For syntax help see: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax +# Note: This file is autogenerated. To make changes to the codeowner team, please update .repo-metadata.json. -# The @googleapis/yoshi-python is the default owner for changes in this repo -* @googleapis/yoshi-python +# @googleapis/yoshi-python @googleapis/cdpe-cloudai are the default owners for changes in this repo +* @googleapis/yoshi-python @googleapis/cdpe-cloudai -# The python-samples-reviewers team is the default owner for samples changes -/samples/ @googleapis/python-samples-owners @googleapis/ml-apis +# @googleapis/python-samples-reviewers @googleapis/cdpe-cloudai are the default owners for samples changes +/samples/ @googleapis/python-samples-reviewers @googleapis/cdpe-cloudai diff --git a/.github/release-please.yml b/.github/release-please.yml index 4507ad05..466597e5 100644 --- a/.github/release-please.yml +++ b/.github/release-please.yml @@ -1 +1,2 @@ releaseType: python +handleGHRelease: true diff --git a/.github/release-trigger.yml b/.github/release-trigger.yml new file mode 100644 index 00000000..d4ca9418 --- /dev/null +++ b/.github/release-trigger.yml @@ -0,0 +1 @@ +enabled: true diff --git a/.kokoro/docs/common.cfg b/.kokoro/docs/common.cfg index c90da11c..ccf3e517 100644 --- a/.kokoro/docs/common.cfg +++ b/.kokoro/docs/common.cfg @@ -30,6 +30,7 @@ env_vars: { env_vars: { key: "V2_STAGING_BUCKET" + # Push google cloud library docs to the Cloud RAD bucket `docs-staging-v2` value: "docs-staging-v2" } diff --git a/.kokoro/release.sh b/.kokoro/release.sh index 4b5e99f5..6c17dc12 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_GFILE_DIR}/secret_manager/google-cloud-pypi-token") +TWINE_PASSWORD=$(cat "${KOKORO_KEYSTORE_DIR}/73713_google-cloud-pypi-token-keystore-1") cd github/python-documentai python3 setup.py sdist bdist_wheel twine upload --username __token__ --password "${TWINE_PASSWORD}" dist/* diff --git a/.kokoro/release/common.cfg b/.kokoro/release/common.cfg index 8f7706a3..47ad0a0f 100644 --- a/.kokoro/release/common.cfg +++ b/.kokoro/release/common.cfg @@ -23,8 +23,18 @@ env_vars: { value: "github/python-documentai/.kokoro/release.sh" } +# Fetch PyPI password +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "google-cloud-pypi-token-keystore-1" + } + } +} + # 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,google-cloud-pypi-token" + value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" } diff --git a/.repo-metadata.json b/.repo-metadata.json index 7e367430..c65045f6 100644 --- a/.repo-metadata.json +++ b/.repo-metadata.json @@ -2,9 +2,9 @@ "name": "documentai", "name_pretty": "Cloud Document Understanding API", "product_documentation": "https://cloud.google.com/document-understanding/docs/", - "client_documentation": "https://googleapis.dev/python/documentai/latest", + "client_documentation": "https://cloud.google.com/python/docs/reference/documentai/latest", "issue_tracker": "", - "release_level": "ga", + "release_level": "stable", "language": "python", "library_type": "GAPIC_AUTO", "repo": "googleapis/python-documentai", @@ -12,5 +12,6 @@ "api_id": "documentai.googleapis.com", "requires_billing": true, "default_version": "v1", - "codeowner_team": "@googleapis/ml-apis" + "codeowner_team": "@googleapis/cdpe-cloudai", + "api_shortname": "documentai" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c7127e1..12d4a184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### [1.2.1](https://github.com/googleapis/python-documentai/compare/v1.2.0...v1.2.1) (2022-01-17) + + +### Bug Fixes + +* **deps:** drop packaging dependency ([038a736](https://github.com/googleapis/python-documentai/commit/038a7364fe0d2341a3bda1e40bfe23d864427ab7)) +* **deps:** require google-api-core >= 1.28.0 ([038a736](https://github.com/googleapis/python-documentai/commit/038a7364fe0d2341a3bda1e40bfe23d864427ab7)) + ## [1.2.0](https://www.github.com/googleapis/python-documentai/compare/v1.1.0...v1.2.0) (2021-10-14) diff --git a/README.rst b/README.rst index e42928fe..c772006e 100644 --- a/README.rst +++ b/README.rst @@ -17,7 +17,7 @@ language, computer vision, translation, and AutoML. .. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-documentai.svg :target: https://pypi.org/project/google-cloud-documentai/ .. _Cloud Document AI API: https://cloud.google.com/document-understanding/docs/ -.. _Client Library Documentation: https://googleapis.dev/python/documentai/latest +.. _Client Library Documentation: https://cloud.google.com/python/docs/reference/documentai/latest .. _Product Documentation: https://cloud.google.com/document-understanding/docs/ Quick Start diff --git a/docs/index.rst b/docs/index.rst index fd5e2754..8488489a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,6 +2,10 @@ .. include:: multiprocessing.rst +This package includes clients for multiple versions of Cloud Document Understanding API. +By default, you will get version ``documentai_v1``. + + API Reference ------------- .. toctree:: @@ -9,11 +13,23 @@ API Reference documentai_v1/services documentai_v1/types - documentai_v1beta3/services - documentai_v1beta3/types + +API Reference +------------- +.. toctree:: + :maxdepth: 2 + documentai_v1beta2/services documentai_v1beta2/types +API Reference +------------- +.. toctree:: + :maxdepth: 2 + + documentai_v1beta3/services + documentai_v1beta3/types + Changelog --------- @@ -21,6 +37,6 @@ Changelog For a list of all ``google-cloud-documentai`` releases: .. toctree:: - :maxdepth: 2 + :maxdepth: 2 - changelog + changelog diff --git a/google/cloud/documentai_v1/services/document_processor_service/async_client.py b/google/cloud/documentai_v1/services/document_processor_service/async_client.py index b4cfb8cd..953934d2 100644 --- a/google/cloud/documentai_v1/services/document_processor_service/async_client.py +++ b/google/cloud/documentai_v1/services/document_processor_service/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # 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.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.documentai_v1.types import document @@ -183,17 +188,17 @@ def __init__( async def process_document( self, - request: document_processor_service.ProcessRequest = None, + request: Union[document_processor_service.ProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document_processor_service.ProcessResponse: r"""Processes a single document. Args: - request (:class:`google.cloud.documentai_v1.types.ProcessRequest`): + request (Union[google.cloud.documentai_v1.types.ProcessRequest, dict]): The request object. Request message for the process document method. name (:class:`str`): @@ -264,10 +269,10 @@ async def process_document( async def batch_process_documents( self, - request: document_processor_service.BatchProcessRequest = None, + request: Union[document_processor_service.BatchProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -275,7 +280,7 @@ async def batch_process_documents( written to Cloud Storage as JSON in the [Document] format. Args: - request (:class:`google.cloud.documentai_v1.types.BatchProcessRequest`): + request (Union[google.cloud.documentai_v1.types.BatchProcessRequest, dict]): The request object. Request message for batch process document method. name (:class:`str`): @@ -357,10 +362,10 @@ async def batch_process_documents( async def review_document( self, - request: document_processor_service.ReviewDocumentRequest = None, + request: Union[document_processor_service.ReviewDocumentRequest, dict] = None, *, human_review_config: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -368,7 +373,7 @@ async def review_document( should be processed by the specified processor. Args: - request (:class:`google.cloud.documentai_v1.types.ReviewDocumentRequest`): + request (Union[google.cloud.documentai_v1.types.ReviewDocumentRequest, dict]): The request object. Request message for review document method. human_review_config (:class:`str`): diff --git a/google/cloud/documentai_v1/services/document_processor_service/client.py b/google/cloud/documentai_v1/services/document_processor_service/client.py index f094486e..b5d44355 100644 --- a/google/cloud/documentai_v1/services/document_processor_service/client.py +++ b/google/cloud/documentai_v1/services/document_processor_service/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # 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.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries 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 +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.documentai_v1.types import document @@ -306,8 +310,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -377,7 +388,7 @@ def process_document( request: Union[document_processor_service.ProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document_processor_service.ProcessResponse: @@ -448,7 +459,7 @@ def batch_process_documents( request: Union[document_processor_service.BatchProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -531,7 +542,7 @@ def review_document( request: Union[document_processor_service.ReviewDocumentRequest, dict] = None, *, human_review_config: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: diff --git a/google/cloud/documentai_v1/services/document_processor_service/transports/base.py b/google/cloud/documentai_v1/services/document_processor_service/transports/base.py index c01879dc..2442802b 100644 --- a/google/cloud/documentai_v1/services/document_processor_service/transports/base.py +++ b/google/cloud/documentai_v1/services/document_processor_service/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources 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.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -39,15 +38,6 @@ 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 - class DocumentProcessorServiceTransport(abc.ABC): """Abstract transport class for DocumentProcessorService.""" @@ -97,7 +87,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -113,7 +103,6 @@ def __init__( credentials, _ = google.auth.load_credentials_from_file( credentials_file, **scopes_kwargs, quota_project_id=quota_project_id ) - elif credentials is None: credentials, _ = google.auth.default( **scopes_kwargs, quota_project_id=quota_project_id @@ -130,29 +119,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is 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 - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -213,7 +179,7 @@ def close(self): raise NotImplementedError() @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/documentai_v1/services/document_processor_service/transports/grpc.py b/google/cloud/documentai_v1/services/document_processor_service/transports/grpc.py index ea350b19..58e02f35 100644 --- a/google/cloud/documentai_v1/services/document_processor_service/transports/grpc.py +++ b/google/cloud/documentai_v1/services/document_processor_service/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -116,7 +116,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) diff --git a/google/cloud/documentai_v1/services/document_processor_service/transports/grpc_asyncio.py b/google/cloud/documentai_v1/services/document_processor_service/transports/grpc_asyncio.py index bfb639af..0578ce72 100644 --- a/google/cloud/documentai_v1/services/document_processor_service/transports/grpc_asyncio.py +++ b/google/cloud/documentai_v1/services/document_processor_service/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings 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.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 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 @@ -163,7 +162,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) diff --git a/google/cloud/documentai_v1/types/document.py b/google/cloud/documentai_v1/types/document.py index 711f7410..ef8a59ac 100644 --- a/google/cloud/documentai_v1/types/document.py +++ b/google/cloud/documentai_v1/types/document.py @@ -37,6 +37,13 @@ class Document(proto.Message): documents and allows for collaboration between users and Document Understanding AI to iterate and optimize for quality. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: uri (str): Optional. Currently supports Google Cloud Storage URI of the @@ -44,11 +51,15 @@ class Document(proto.Message): not supported. See `Google Cloud Storage Request URIs `__ for more info. + + This field is a member of `oneof`_ ``source``. content (bytes): Optional. Inline document content, represented as a stream of bytes. Note: As with all ``bytes`` fields, protobuffers use a pure binary representation, whereas JSON representations use base64. + + This field is a member of `oneof`_ ``source``. mime_type (str): An IANA published MIME type (also referred to as media type). For more information, see @@ -683,24 +694,41 @@ class Entity(proto.Message): class NormalizedValue(proto.Message): r"""Parsed and normalized entity value. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: money_value (google.type.money_pb2.Money): Money value. See also: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto + + This field is a member of `oneof`_ ``structured_value``. date_value (google.type.date_pb2.Date): Date value. Includes year, month, day. See also: https://github.com/googleapis/googleapis/blob/master/google/type/date.proto + + This field is a member of `oneof`_ ``structured_value``. datetime_value (google.type.datetime_pb2.DateTime): DateTime value. Includes date, time, and timezone. See also: https://github.com/googleapis/googleapis/blob/master/google/type/datetime.proto + + This field is a member of `oneof`_ ``structured_value``. address_value (google.type.postal_address_pb2.PostalAddress): Postal address. See also: https://github.com/googleapis/googleapis/blob/master/google/type/postal_address.proto + + This field is a member of `oneof`_ ``structured_value``. boolean_value (bool): Boolean value. Can be used for entities with binary values, or for checkboxes. + + This field is a member of `oneof`_ ``structured_value``. text (str): Required. Normalized entity value stored as a string. This field is populated for supported document type (e.g. @@ -947,13 +975,24 @@ class Parent(proto.Message): class Revision(proto.Message): r"""Contains past or forward revisions of this document. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: agent (str): If the change was made by a person specify the name or id of that person. + + This field is a member of `oneof`_ ``source``. processor (str): If the annotation was made by processor identify the processor by its resource name. + + This field is a member of `oneof`_ ``source``. id (str): Id of the revision. Unique within the context of the document. diff --git a/google/cloud/documentai_v1/types/document_io.py b/google/cloud/documentai_v1/types/document_io.py index 4692f6d9..06b3d1cc 100644 --- a/google/cloud/documentai_v1/types/document_io.py +++ b/google/cloud/documentai_v1/types/document_io.py @@ -85,13 +85,24 @@ class BatchDocumentsInputConfig(proto.Message): r"""The common config to specify a set of documents used as input. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: gcs_prefix (google.cloud.documentai_v1.types.GcsPrefix): The set of documents that match the specified Cloud Storage [gcs_prefix]. + + This field is a member of `oneof`_ ``source``. gcs_documents (google.cloud.documentai_v1.types.GcsDocuments): The set of documents individually specified on Cloud Storage. + + This field is a member of `oneof`_ ``source``. """ gcs_prefix = proto.Field( @@ -106,10 +117,15 @@ class DocumentOutputConfig(proto.Message): r"""Config that controls the output of documents. All documents will be written as a JSON file. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: gcs_output_config (google.cloud.documentai_v1.types.DocumentOutputConfig.GcsOutputConfig): Output config to write the results to Cloud Storage. + + This field is a member of `oneof`_ ``destination``. """ class GcsOutputConfig(proto.Message): diff --git a/google/cloud/documentai_v1/types/document_processor_service.py b/google/cloud/documentai_v1/types/document_processor_service.py index 8955dfe2..d94bee45 100644 --- a/google/cloud/documentai_v1/types/document_processor_service.py +++ b/google/cloud/documentai_v1/types/document_processor_service.py @@ -41,11 +41,22 @@ class ProcessRequest(proto.Message): r"""Request message for the process document method. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: inline_document (google.cloud.documentai_v1.types.Document): An inline document proto. + + This field is a member of `oneof`_ ``source``. raw_document (google.cloud.documentai_v1.types.RawDocument): A raw document content (bytes). + + This field is a member of `oneof`_ ``source``. name (str): Required. The processor resource name. skip_human_review (bool): @@ -212,9 +223,13 @@ class IndividualProcessStatus(proto.Message): class ReviewDocumentRequest(proto.Message): r"""Request message for review document method. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: inline_document (google.cloud.documentai_v1.types.Document): An inline document proto. + + This field is a member of `oneof`_ ``source``. human_review_config (str): Required. The resource name of the HumanReviewConfig that the document will be diff --git a/google/cloud/documentai_v1beta2/services/document_understanding_service/async_client.py b/google/cloud/documentai_v1beta2/services/document_understanding_service/async_client.py index 206ccd6e..c41655ee 100644 --- a/google/cloud/documentai_v1beta2/services/document_understanding_service/async_client.py +++ b/google/cloud/documentai_v1beta2/services/document_understanding_service/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # 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.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.documentai_v1beta2.types import document @@ -174,10 +179,12 @@ def __init__( async def batch_process_documents( self, - request: document_understanding.BatchProcessDocumentsRequest = None, + request: Union[ + document_understanding.BatchProcessDocumentsRequest, dict + ] = None, *, requests: Sequence[document_understanding.ProcessDocumentRequest] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -185,7 +192,7 @@ async def batch_process_documents( written to Cloud Storage as JSON in the [Document] format. Args: - request (:class:`google.cloud.documentai_v1beta2.types.BatchProcessDocumentsRequest`): + request (Union[google.cloud.documentai_v1beta2.types.BatchProcessDocumentsRequest, dict]): The request object. Request to batch process documents as an asynchronous operation. The output is written to Cloud Storage as JSON in the [Document] format. @@ -267,16 +274,16 @@ async def batch_process_documents( async def process_document( self, - request: document_understanding.ProcessDocumentRequest = None, + request: Union[document_understanding.ProcessDocumentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document.Document: r"""Processes a single document. Args: - request (:class:`google.cloud.documentai_v1beta2.types.ProcessDocumentRequest`): + request (Union[google.cloud.documentai_v1beta2.types.ProcessDocumentRequest, dict]): The request object. Request to process one document. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. diff --git a/google/cloud/documentai_v1beta2/services/document_understanding_service/client.py b/google/cloud/documentai_v1beta2/services/document_understanding_service/client.py index a35bd037..1d7bec4a 100644 --- a/google/cloud/documentai_v1beta2/services/document_understanding_service/client.py +++ b/google/cloud/documentai_v1beta2/services/document_understanding_service/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # 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.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries 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 +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.documentai_v1beta2.types import document @@ -277,8 +281,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -350,7 +361,7 @@ def batch_process_documents( ] = None, *, requests: Sequence[document_understanding.ProcessDocumentRequest] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -432,7 +443,7 @@ def process_document( self, request: Union[document_understanding.ProcessDocumentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document.Document: diff --git a/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/base.py b/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/base.py index bd478c7b..2907c6c7 100644 --- a/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/base.py +++ b/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources 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.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -40,15 +39,6 @@ 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 - class DocumentUnderstandingServiceTransport(abc.ABC): """Abstract transport class for DocumentUnderstandingService.""" @@ -98,7 +88,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -114,7 +104,6 @@ def __init__( credentials, _ = google.auth.load_credentials_from_file( credentials_file, **scopes_kwargs, quota_project_id=quota_project_id ) - elif credentials is None: credentials, _ = google.auth.default( **scopes_kwargs, quota_project_id=quota_project_id @@ -131,29 +120,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is 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 - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -199,7 +165,7 @@ def close(self): raise NotImplementedError() @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc.py b/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc.py index 6c42f801..c08a8db1 100644 --- a/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc.py +++ b/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -115,7 +115,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) diff --git a/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc_asyncio.py b/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc_asyncio.py index fabd9696..238594d1 100644 --- a/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc_asyncio.py +++ b/google/cloud/documentai_v1beta2/services/document_understanding_service/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings 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.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 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 @@ -164,7 +163,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) diff --git a/google/cloud/documentai_v1beta2/types/document.py b/google/cloud/documentai_v1beta2/types/document.py index 5b421477..b58ec2b9 100644 --- a/google/cloud/documentai_v1beta2/types/document.py +++ b/google/cloud/documentai_v1beta2/types/document.py @@ -32,6 +32,13 @@ class Document(proto.Message): documents and allows for collaboration between users and Document Understanding AI to iterate and optimize for quality. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: uri (str): Currently supports Google Cloud Storage URI of the form @@ -39,11 +46,15 @@ class Document(proto.Message): supported. See `Google Cloud Storage Request URIs `__ for more info. + + This field is a member of `oneof`_ ``source``. content (bytes): Inline document content, represented as a stream of bytes. Note: As with all ``bytes`` fields, protobuffers use a pure binary representation, whereas JSON representations use base64. + + This field is a member of `oneof`_ ``source``. mime_type (str): An IANA published MIME type (also referred to as media type). For more information, see @@ -107,6 +118,9 @@ class Label(proto.Message): instances of the same label created at different times, or some combination of both. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: automl_model (str): Label is generated AutoML model. This field stores the full @@ -114,6 +128,8 @@ class Label(proto.Message): Format: ``projects/{project-id}/locations/{location-id}/models/{model-id}`` + + This field is a member of `oneof`_ ``source``. name (str): Name of the label. When the label is generated from AutoML Text diff --git a/google/cloud/documentai_v1beta2/types/document_understanding.py b/google/cloud/documentai_v1beta2/types/document_understanding.py index f36ad3b5..d1393675 100644 --- a/google/cloud/documentai_v1beta2/types/document_understanding.py +++ b/google/cloud/documentai_v1beta2/types/document_understanding.py @@ -314,10 +314,19 @@ class AutoMlParams(proto.Message): class InputConfig(proto.Message): r"""The desired input location and metadata. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: gcs_source (google.cloud.documentai_v1beta2.types.GcsSource): The Google Cloud Storage location to read the input from. This must be a single file. + + This field is a member of `oneof`_ ``source``. contents (bytes): Content in bytes, represented as a stream of bytes. Note: As with all ``bytes`` fields, proto buffer messages use a pure @@ -326,6 +335,8 @@ class InputConfig(proto.Message): This field only works for synchronous ProcessDocument method. + + This field is a member of `oneof`_ ``source``. mime_type (str): Required. Mimetype of the input. Current supported mimetypes are application/pdf, image/tiff, and image/gif. In addition, @@ -345,10 +356,14 @@ class InputConfig(proto.Message): class OutputConfig(proto.Message): r"""The desired output location and metadata. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: gcs_destination (google.cloud.documentai_v1beta2.types.GcsDestination): The Google Cloud Storage location to write the output to. + + This field is a member of `oneof`_ ``destination``. pages_per_shard (int): The max number of pages to include into each output Document shard JSON on Google Cloud Storage. diff --git a/google/cloud/documentai_v1beta3/services/document_processor_service/async_client.py b/google/cloud/documentai_v1beta3/services/document_processor_service/async_client.py index ea5a8ffa..534699e1 100644 --- a/google/cloud/documentai_v1beta3/services/document_processor_service/async_client.py +++ b/google/cloud/documentai_v1beta3/services/document_processor_service/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # 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.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.documentai_v1beta3.services.document_processor_service import pagers @@ -195,17 +200,17 @@ def __init__( async def process_document( self, - request: document_processor_service.ProcessRequest = None, + request: Union[document_processor_service.ProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document_processor_service.ProcessResponse: r"""Processes a single document. Args: - request (:class:`google.cloud.documentai_v1beta3.types.ProcessRequest`): + request (Union[google.cloud.documentai_v1beta3.types.ProcessRequest, dict]): The request object. Request message for the process document method. name (:class:`str`): @@ -276,10 +281,10 @@ async def process_document( async def batch_process_documents( self, - request: document_processor_service.BatchProcessRequest = None, + request: Union[document_processor_service.BatchProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -287,7 +292,7 @@ async def batch_process_documents( written to Cloud Storage as JSON in the [Document] format. Args: - request (:class:`google.cloud.documentai_v1beta3.types.BatchProcessRequest`): + request (Union[google.cloud.documentai_v1beta3.types.BatchProcessRequest, dict]): The request object. Request message for batch process document method. name (:class:`str`): @@ -369,17 +374,19 @@ async def batch_process_documents( async def fetch_processor_types( self, - request: document_processor_service.FetchProcessorTypesRequest = None, + request: Union[ + document_processor_service.FetchProcessorTypesRequest, dict + ] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document_processor_service.FetchProcessorTypesResponse: r"""Fetches processor types. Args: - request (:class:`google.cloud.documentai_v1beta3.types.FetchProcessorTypesRequest`): + request (Union[google.cloud.documentai_v1beta3.types.FetchProcessorTypesRequest, dict]): The request object. Request message for fetch processor types. parent (:class:`str`): @@ -441,17 +448,17 @@ async def fetch_processor_types( async def list_processors( self, - request: document_processor_service.ListProcessorsRequest = None, + request: Union[document_processor_service.ListProcessorsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListProcessorsAsyncPager: r"""Lists all processors which belong to this project. Args: - request (:class:`google.cloud.documentai_v1beta3.types.ListProcessorsRequest`): + request (Union[google.cloud.documentai_v1beta3.types.ListProcessorsRequest, dict]): The request object. Request message for list all processors belongs to a project. parent (:class:`str`): @@ -522,11 +529,11 @@ async def list_processors( async def create_processor( self, - request: document_processor_service.CreateProcessorRequest = None, + request: Union[document_processor_service.CreateProcessorRequest, dict] = None, *, parent: str = None, processor: gcd_processor.Processor = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_processor.Processor: @@ -535,7 +542,7 @@ async def create_processor( default after its creation. Args: - request (:class:`google.cloud.documentai_v1beta3.types.CreateProcessorRequest`): + request (Union[google.cloud.documentai_v1beta3.types.CreateProcessorRequest, dict]): The request object. Request message for create a processor. Notice this request is sent to a regionalized backend service, and if the processor type is not @@ -612,10 +619,10 @@ async def create_processor( async def delete_processor( self, - request: document_processor_service.DeleteProcessorRequest = None, + request: Union[document_processor_service.DeleteProcessorRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -624,7 +631,7 @@ async def delete_processor( artifacts associated with this processor. Args: - request (:class:`google.cloud.documentai_v1beta3.types.DeleteProcessorRequest`): + request (Union[google.cloud.documentai_v1beta3.types.DeleteProcessorRequest, dict]): The request object. Request message for the delete processor method. name (:class:`str`): @@ -706,16 +713,16 @@ async def delete_processor( async def enable_processor( self, - request: document_processor_service.EnableProcessorRequest = None, + request: Union[document_processor_service.EnableProcessorRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: r"""Enables a processor Args: - request (:class:`google.cloud.documentai_v1beta3.types.EnableProcessorRequest`): + request (Union[google.cloud.documentai_v1beta3.types.EnableProcessorRequest, dict]): The request object. Request message for the enable processor method. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -766,16 +773,16 @@ async def enable_processor( async def disable_processor( self, - request: document_processor_service.DisableProcessorRequest = None, + request: Union[document_processor_service.DisableProcessorRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: r"""Disables a processor Args: - request (:class:`google.cloud.documentai_v1beta3.types.DisableProcessorRequest`): + request (Union[google.cloud.documentai_v1beta3.types.DisableProcessorRequest, dict]): The request object. Request message for the disable processor method. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -826,10 +833,10 @@ async def disable_processor( async def review_document( self, - request: document_processor_service.ReviewDocumentRequest = None, + request: Union[document_processor_service.ReviewDocumentRequest, dict] = None, *, human_review_config: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -837,7 +844,7 @@ async def review_document( should be processed by the specified processor. Args: - request (:class:`google.cloud.documentai_v1beta3.types.ReviewDocumentRequest`): + request (Union[google.cloud.documentai_v1beta3.types.ReviewDocumentRequest, dict]): The request object. Request message for review document method. Next Id: 6. human_review_config (:class:`str`): diff --git a/google/cloud/documentai_v1beta3/services/document_processor_service/client.py b/google/cloud/documentai_v1beta3/services/document_processor_service/client.py index 958223dc..ca22871e 100644 --- a/google/cloud/documentai_v1beta3/services/document_processor_service/client.py +++ b/google/cloud/documentai_v1beta3/services/document_processor_service/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # 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.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries 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 +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.documentai_v1beta3.services.document_processor_service import pagers @@ -328,8 +332,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -399,7 +410,7 @@ def process_document( request: Union[document_processor_service.ProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document_processor_service.ProcessResponse: @@ -470,7 +481,7 @@ def batch_process_documents( request: Union[document_processor_service.BatchProcessRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -555,7 +566,7 @@ def fetch_processor_types( ] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document_processor_service.FetchProcessorTypesResponse: @@ -629,7 +640,7 @@ def list_processors( request: Union[document_processor_service.ListProcessorsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListProcessorsPager: @@ -711,7 +722,7 @@ def create_processor( *, parent: str = None, processor: gcd_processor.Processor = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_processor.Processor: @@ -800,7 +811,7 @@ def delete_processor( request: Union[document_processor_service.DeleteProcessorRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -893,7 +904,7 @@ def enable_processor( self, request: Union[document_processor_service.EnableProcessorRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -954,7 +965,7 @@ def disable_processor( self, request: Union[document_processor_service.DisableProcessorRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1016,7 +1027,7 @@ def review_document( request: Union[document_processor_service.ReviewDocumentRequest, dict] = None, *, human_review_config: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: diff --git a/google/cloud/documentai_v1beta3/services/document_processor_service/transports/base.py b/google/cloud/documentai_v1beta3/services/document_processor_service/transports/base.py index fa1b23f2..775dce99 100644 --- a/google/cloud/documentai_v1beta3/services/document_processor_service/transports/base.py +++ b/google/cloud/documentai_v1beta3/services/document_processor_service/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources 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.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -40,15 +39,6 @@ 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 - class DocumentProcessorServiceTransport(abc.ABC): """Abstract transport class for DocumentProcessorService.""" @@ -98,7 +88,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -114,7 +104,6 @@ def __init__( credentials, _ = google.auth.load_credentials_from_file( credentials_file, **scopes_kwargs, quota_project_id=quota_project_id ) - elif credentials is None: credentials, _ = google.auth.default( **scopes_kwargs, quota_project_id=quota_project_id @@ -131,29 +120,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is 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 - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -234,7 +200,7 @@ def close(self): raise NotImplementedError() @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc.py b/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc.py index 8382c9d5..ec345fc9 100644 --- a/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc.py +++ b/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -117,7 +117,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) diff --git a/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc_asyncio.py b/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc_asyncio.py index fd19a769..b5e9f687 100644 --- a/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc_asyncio.py +++ b/google/cloud/documentai_v1beta3/services/document_processor_service/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings 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.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 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 @@ -164,7 +163,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) diff --git a/google/cloud/documentai_v1beta3/types/document.py b/google/cloud/documentai_v1beta3/types/document.py index 6c428279..1f02f195 100644 --- a/google/cloud/documentai_v1beta3/types/document.py +++ b/google/cloud/documentai_v1beta3/types/document.py @@ -37,6 +37,13 @@ class Document(proto.Message): documents and allows for collaboration between users and Document Understanding AI to iterate and optimize for quality. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: uri (str): Optional. Currently supports Google Cloud Storage URI of the @@ -44,11 +51,15 @@ class Document(proto.Message): not supported. See `Google Cloud Storage Request URIs `__ for more info. + + This field is a member of `oneof`_ ``source``. content (bytes): Optional. Inline document content, represented as a stream of bytes. Note: As with all ``bytes`` fields, protobuffers use a pure binary representation, whereas JSON representations use base64. + + This field is a member of `oneof`_ ``source``. mime_type (str): An IANA published MIME type (also referred to as media type). For more information, see @@ -687,24 +698,41 @@ class Entity(proto.Message): class NormalizedValue(proto.Message): r"""Parsed and normalized entity value. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: money_value (google.type.money_pb2.Money): Money value. See also: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto + + This field is a member of `oneof`_ ``structured_value``. date_value (google.type.date_pb2.Date): Date value. Includes year, month, day. See also: https://github.com/googleapis/googleapis/blob/master/google/type/date.proto + + This field is a member of `oneof`_ ``structured_value``. datetime_value (google.type.datetime_pb2.DateTime): DateTime value. Includes date, time, and timezone. See also: https://github.com/googleapis/googleapis/blob/master/google/type/datetime.proto + + This field is a member of `oneof`_ ``structured_value``. address_value (google.type.postal_address_pb2.PostalAddress): Postal address. See also: https://github.com/googleapis/googleapis/blob/master/google/type/postal_address.proto + + This field is a member of `oneof`_ ``structured_value``. boolean_value (bool): Boolean value. Can be used for entities with binary values, or for checkboxes. + + This field is a member of `oneof`_ ``structured_value``. text (str): Required. Normalized entity value stored as a string. This field is populated for supported document type (e.g. @@ -951,13 +979,24 @@ class Parent(proto.Message): class Revision(proto.Message): r"""Contains past or forward revisions of this document. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: agent (str): If the change was made by a person specify the name or id of that person. + + This field is a member of `oneof`_ ``source``. processor (str): If the annotation was made by processor identify the processor by its resource name. + + This field is a member of `oneof`_ ``source``. id (str): Id of the revision. Unique within the context of the document. diff --git a/google/cloud/documentai_v1beta3/types/document_io.py b/google/cloud/documentai_v1beta3/types/document_io.py index 71831439..2a9d84e7 100644 --- a/google/cloud/documentai_v1beta3/types/document_io.py +++ b/google/cloud/documentai_v1beta3/types/document_io.py @@ -85,13 +85,24 @@ class BatchDocumentsInputConfig(proto.Message): r"""The common config to specify a set of documents used as input. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: gcs_prefix (google.cloud.documentai_v1beta3.types.GcsPrefix): The set of documents that match the specified Cloud Storage [gcs_prefix]. + + This field is a member of `oneof`_ ``source``. gcs_documents (google.cloud.documentai_v1beta3.types.GcsDocuments): The set of documents individually specified on Cloud Storage. + + This field is a member of `oneof`_ ``source``. """ gcs_prefix = proto.Field( @@ -106,10 +117,15 @@ class DocumentOutputConfig(proto.Message): r"""Config that controls the output of documents. All documents will be written as a JSON file. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: gcs_output_config (google.cloud.documentai_v1beta3.types.DocumentOutputConfig.GcsOutputConfig): Output config to write the results to Cloud Storage. + + This field is a member of `oneof`_ ``destination``. """ class GcsOutputConfig(proto.Message): diff --git a/google/cloud/documentai_v1beta3/types/document_processor_service.py b/google/cloud/documentai_v1beta3/types/document_processor_service.py index 7a26d2bc..a7980cbe 100644 --- a/google/cloud/documentai_v1beta3/types/document_processor_service.py +++ b/google/cloud/documentai_v1beta3/types/document_processor_service.py @@ -56,11 +56,22 @@ class ProcessRequest(proto.Message): r"""Request message for the process document method. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: inline_document (google.cloud.documentai_v1beta3.types.Document): An inline document proto. + + This field is a member of `oneof`_ ``source``. raw_document (google.cloud.documentai_v1beta3.types.RawDocument): A raw document content (bytes). + + This field is a member of `oneof`_ ``source``. name (str): Required. The processor resource name. document (google.cloud.documentai_v1beta3.types.Document): @@ -467,9 +478,14 @@ class ReviewDocumentRequest(proto.Message): r"""Request message for review document method. Next Id: 6. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: inline_document (google.cloud.documentai_v1beta3.types.Document): An inline document proto. + + This field is a member of `oneof`_ ``source``. human_review_config (str): Required. The resource name of the HumanReviewConfig that the document will be diff --git a/noxfile.py b/noxfile.py index f885c682..2a2001c4 100644 --- a/noxfile.py +++ b/noxfile.py @@ -101,7 +101,7 @@ def default(session): "py.test", "--quiet", f"--junitxml=unit_{session.python}_sponge_log.xml", - "--cov=google/cloud", + "--cov=google", "--cov=tests/unit", "--cov-append", "--cov-config=.coveragerc", @@ -175,7 +175,7 @@ def cover(session): test runs (not system test runs), and then erases coverage data. """ session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=99") + session.run("coverage", "report", "--show-missing", "--fail-under=100") session.run("coverage", "erase") diff --git a/owlbot.py b/owlbot.py deleted file mode 100644 index ac14bcd2..00000000 --- a/owlbot.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2018 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. - -"""This script is used to synthesize generated parts of this library.""" -import re - -from synthtool.languages import python - -import synthtool as s -import synthtool.gcp as gcp -import logging - -logging.basicConfig(level=logging.DEBUG) - -common = gcp.CommonTemplates() - -default_version = "v1" - -for library in s.get_staging_dirs(default_version): - excludes = [ - "README.rst", - "docs/index.rst", - "setup.py", - "scripts/fixup_documentai_v*", # this library was always generated with the microgenerator - ] - - s.move(library, excludes=excludes) - -s.remove_staging_dirs() - -# ---------------------------------------------------------------------------- -# Add templated files -# ---------------------------------------------------------------------------- -templated_files = common.py_library( - cov_level=99, microgenerator=True, samples=False, # set to true if there are samples -) - -s.move( - templated_files, - excludes=[".coveragerc"], # microgenerator has a good .coveragerc file -) - -python.py_samples(skip_readmes=True) - -s.shell.run(["nox", "-s", "blacken"], hide_output=False) - diff --git a/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_batch_process_documents_async.py b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_batch_process_documents_async.py new file mode 100644 index 00000000..1bd888b5 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_batch_process_documents_async.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchProcessDocuments +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1_DocumentProcessorService_BatchProcessDocuments_async] +from google.cloud import documentai_v1 + + +async def sample_batch_process_documents(): + """Snippet for batch_process_documents""" + + # Create a client + client = documentai_v1.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1.BatchProcessRequest( + name=name, + ) + + # Make the request + operation = client.batch_process_documents(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + print(response) + +# [END documentai_generated_documentai_v1_DocumentProcessorService_BatchProcessDocuments_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_batch_process_documents_sync.py b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_batch_process_documents_sync.py new file mode 100644 index 00000000..ae827a1c --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_batch_process_documents_sync.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchProcessDocuments +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1_DocumentProcessorService_BatchProcessDocuments_sync] +from google.cloud import documentai_v1 + + +def sample_batch_process_documents(): + """Snippet for batch_process_documents""" + + # Create a client + client = documentai_v1.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1.BatchProcessRequest( + name=name, + ) + + # Make the request + operation = client.batch_process_documents(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + print(response) + +# [END documentai_generated_documentai_v1_DocumentProcessorService_BatchProcessDocuments_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_process_document_async.py b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_process_document_async.py new file mode 100644 index 00000000..b09a7917 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_process_document_async.py @@ -0,0 +1,56 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ProcessDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1_DocumentProcessorService_ProcessDocument_async] +from google.cloud import documentai_v1 + + +async def sample_process_document(): + """Snippet for process_document""" + + # Create a client + client = documentai_v1.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + inline_document = documentai_v1.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1.ProcessRequest( + inline_document=inline_document, + name=name, + ) + + # Make the request + response = await client.process_document(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1_DocumentProcessorService_ProcessDocument_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_process_document_sync.py b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_process_document_sync.py new file mode 100644 index 00000000..f7c58628 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_process_document_sync.py @@ -0,0 +1,56 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ProcessDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1_DocumentProcessorService_ProcessDocument_sync] +from google.cloud import documentai_v1 + + +def sample_process_document(): + """Snippet for process_document""" + + # Create a client + client = documentai_v1.DocumentProcessorServiceClient() + + # Initialize request argument(s) + inline_document = documentai_v1.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1.ProcessRequest( + inline_document=inline_document, + name=name, + ) + + # Make the request + response = client.process_document(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1_DocumentProcessorService_ProcessDocument_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_review_document_async.py b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_review_document_async.py new file mode 100644 index 00000000..afd5c6dc --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_review_document_async.py @@ -0,0 +1,58 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ReviewDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1_DocumentProcessorService_ReviewDocument_async] +from google.cloud import documentai_v1 + + +async def sample_review_document(): + """Snippet for review_document""" + + # Create a client + client = documentai_v1.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + inline_document = documentai_v1.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + human_review_config = f"projects/{project}/locations/{location}/processors/{processor}/humanReviewConfig" + + request = documentai_v1.ReviewDocumentRequest( + inline_document=inline_document, + human_review_config=human_review_config, + ) + + # Make the request + operation = client.review_document(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + print(response) + +# [END documentai_generated_documentai_v1_DocumentProcessorService_ReviewDocument_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_review_document_sync.py b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_review_document_sync.py new file mode 100644 index 00000000..ce4d7b25 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1_document_processor_service_review_document_sync.py @@ -0,0 +1,58 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ReviewDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1_DocumentProcessorService_ReviewDocument_sync] +from google.cloud import documentai_v1 + + +def sample_review_document(): + """Snippet for review_document""" + + # Create a client + client = documentai_v1.DocumentProcessorServiceClient() + + # Initialize request argument(s) + inline_document = documentai_v1.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + human_review_config = f"projects/{project}/locations/{location}/processors/{processor}/humanReviewConfig" + + request = documentai_v1.ReviewDocumentRequest( + inline_document=inline_document, + human_review_config=human_review_config, + ) + + # Make the request + operation = client.review_document(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + print(response) + +# [END documentai_generated_documentai_v1_DocumentProcessorService_ReviewDocument_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_batch_process_documents_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_batch_process_documents_async.py new file mode 100644 index 00000000..63b5ff54 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_batch_process_documents_async.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchProcessDocuments +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_BatchProcessDocuments_async] +from google.cloud import documentai_v1beta3 + + +async def sample_batch_process_documents(): + """Snippet for batch_process_documents""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.BatchProcessRequest( + name=name, + ) + + # Make the request + operation = client.batch_process_documents(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_BatchProcessDocuments_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_batch_process_documents_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_batch_process_documents_sync.py new file mode 100644 index 00000000..0e541965 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_batch_process_documents_sync.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchProcessDocuments +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_BatchProcessDocuments_sync] +from google.cloud import documentai_v1beta3 + + +def sample_batch_process_documents(): + """Snippet for batch_process_documents""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.BatchProcessRequest( + name=name, + ) + + # Make the request + operation = client.batch_process_documents(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_BatchProcessDocuments_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_create_processor_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_create_processor_async.py new file mode 100644 index 00000000..05ed108f --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_create_processor_async.py @@ -0,0 +1,52 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for CreateProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_CreateProcessor_async] +from google.cloud import documentai_v1beta3 + + +async def sample_create_processor(): + """Snippet for create_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + parent = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.CreateProcessorRequest( + parent=parent, + ) + + # Make the request + response = await client.create_processor(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_CreateProcessor_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_create_processor_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_create_processor_sync.py new file mode 100644 index 00000000..edef2692 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_create_processor_sync.py @@ -0,0 +1,52 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for CreateProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_CreateProcessor_sync] +from google.cloud import documentai_v1beta3 + + +def sample_create_processor(): + """Snippet for create_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + parent = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.CreateProcessorRequest( + parent=parent, + ) + + # Make the request + response = client.create_processor(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_CreateProcessor_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_delete_processor_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_delete_processor_async.py new file mode 100644 index 00000000..10ac66e8 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_delete_processor_async.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for DeleteProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_DeleteProcessor_async] +from google.cloud import documentai_v1beta3 + + +async def sample_delete_processor(): + """Snippet for delete_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.DeleteProcessorRequest( + name=name, + ) + + # Make the request + operation = client.delete_processor(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_DeleteProcessor_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_delete_processor_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_delete_processor_sync.py new file mode 100644 index 00000000..fbb5dd84 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_delete_processor_sync.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for DeleteProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_DeleteProcessor_sync] +from google.cloud import documentai_v1beta3 + + +def sample_delete_processor(): + """Snippet for delete_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.DeleteProcessorRequest( + name=name, + ) + + # Make the request + operation = client.delete_processor(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_DeleteProcessor_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_disable_processor_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_disable_processor_async.py new file mode 100644 index 00000000..32907a2a --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_disable_processor_async.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for DisableProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_DisableProcessor_async] +from google.cloud import documentai_v1beta3 + + +async def sample_disable_processor(): + """Snippet for disable_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.DisableProcessorRequest( + name=name, + ) + + # Make the request + operation = client.disable_processor(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_DisableProcessor_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_disable_processor_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_disable_processor_sync.py new file mode 100644 index 00000000..f4fa53e5 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_disable_processor_sync.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for DisableProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_DisableProcessor_sync] +from google.cloud import documentai_v1beta3 + + +def sample_disable_processor(): + """Snippet for disable_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.DisableProcessorRequest( + name=name, + ) + + # Make the request + operation = client.disable_processor(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_DisableProcessor_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_enable_processor_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_enable_processor_async.py new file mode 100644 index 00000000..515fa7bd --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_enable_processor_async.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for EnableProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_EnableProcessor_async] +from google.cloud import documentai_v1beta3 + + +async def sample_enable_processor(): + """Snippet for enable_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.EnableProcessorRequest( + name=name, + ) + + # Make the request + operation = client.enable_processor(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_EnableProcessor_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_enable_processor_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_enable_processor_sync.py new file mode 100644 index 00000000..17cc9f76 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_enable_processor_sync.py @@ -0,0 +1,54 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for EnableProcessor +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_EnableProcessor_sync] +from google.cloud import documentai_v1beta3 + + +def sample_enable_processor(): + """Snippet for enable_processor""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.EnableProcessorRequest( + name=name, + ) + + # Make the request + operation = client.enable_processor(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_EnableProcessor_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_fetch_processor_types_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_fetch_processor_types_async.py new file mode 100644 index 00000000..ba9971de --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_fetch_processor_types_async.py @@ -0,0 +1,52 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for FetchProcessorTypes +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_FetchProcessorTypes_async] +from google.cloud import documentai_v1beta3 + + +async def sample_fetch_processor_types(): + """Snippet for fetch_processor_types""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor_type = "processor_type_value" + parent = f"projects/{project}/locations/{location}/processorTypes/{processor_type}" + + request = documentai_v1beta3.FetchProcessorTypesRequest( + parent=parent, + ) + + # Make the request + response = await client.fetch_processor_types(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_FetchProcessorTypes_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_fetch_processor_types_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_fetch_processor_types_sync.py new file mode 100644 index 00000000..5d2cde3f --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_fetch_processor_types_sync.py @@ -0,0 +1,52 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for FetchProcessorTypes +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_FetchProcessorTypes_sync] +from google.cloud import documentai_v1beta3 + + +def sample_fetch_processor_types(): + """Snippet for fetch_processor_types""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor_type = "processor_type_value" + parent = f"projects/{project}/locations/{location}/processorTypes/{processor_type}" + + request = documentai_v1beta3.FetchProcessorTypesRequest( + parent=parent, + ) + + # Make the request + response = client.fetch_processor_types(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_FetchProcessorTypes_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_list_processors_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_list_processors_async.py new file mode 100644 index 00000000..2cf1a9e1 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_list_processors_async.py @@ -0,0 +1,51 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListProcessors +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_ListProcessors_async] +from google.cloud import documentai_v1beta3 + + +async def sample_list_processors(): + """Snippet for list_processors""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + parent = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.ListProcessorsRequest( + parent=parent, + ) + + # Make the request + page_result = client.list_processors(request=request) + async for response in page_result: + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_ListProcessors_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_list_processors_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_list_processors_sync.py new file mode 100644 index 00000000..6d84b5e5 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_list_processors_sync.py @@ -0,0 +1,51 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListProcessors +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_ListProcessors_sync] +from google.cloud import documentai_v1beta3 + + +def sample_list_processors(): + """Snippet for list_processors""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + parent = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.ListProcessorsRequest( + parent=parent, + ) + + # Make the request + page_result = client.list_processors(request=request) + for response in page_result: + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_ListProcessors_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_process_document_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_process_document_async.py new file mode 100644 index 00000000..46c9c117 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_process_document_async.py @@ -0,0 +1,56 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ProcessDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_ProcessDocument_async] +from google.cloud import documentai_v1beta3 + + +async def sample_process_document(): + """Snippet for process_document""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + inline_document = documentai_v1beta3.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.ProcessRequest( + inline_document=inline_document, + name=name, + ) + + # Make the request + response = await client.process_document(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_ProcessDocument_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_process_document_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_process_document_sync.py new file mode 100644 index 00000000..259d85c9 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_process_document_sync.py @@ -0,0 +1,56 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ProcessDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_ProcessDocument_sync] +from google.cloud import documentai_v1beta3 + + +def sample_process_document(): + """Snippet for process_document""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + inline_document = documentai_v1beta3.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + name = f"projects/{project}/locations/{location}/processors/{processor}" + + request = documentai_v1beta3.ProcessRequest( + inline_document=inline_document, + name=name, + ) + + # Make the request + response = client.process_document(request=request) + + # Handle response + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_ProcessDocument_sync] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_review_document_async.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_review_document_async.py new file mode 100644 index 00000000..c40c5d9c --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_review_document_async.py @@ -0,0 +1,58 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ReviewDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_ReviewDocument_async] +from google.cloud import documentai_v1beta3 + + +async def sample_review_document(): + """Snippet for review_document""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceAsyncClient() + + # Initialize request argument(s) + inline_document = documentai_v1beta3.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + human_review_config = f"projects/{project}/locations/{location}/processors/{processor}/humanReviewConfig" + + request = documentai_v1beta3.ReviewDocumentRequest( + inline_document=inline_document, + human_review_config=human_review_config, + ) + + # Make the request + operation = client.review_document(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_ReviewDocument_async] diff --git a/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_review_document_sync.py b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_review_document_sync.py new file mode 100644 index 00000000..30d55799 --- /dev/null +++ b/samples/generated_samples/documentai_generated_documentai_v1beta3_document_processor_service_review_document_sync.py @@ -0,0 +1,58 @@ +# -*- 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. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ReviewDocument +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-documentai + + +# [START documentai_generated_documentai_v1beta3_DocumentProcessorService_ReviewDocument_sync] +from google.cloud import documentai_v1beta3 + + +def sample_review_document(): + """Snippet for review_document""" + + # Create a client + client = documentai_v1beta3.DocumentProcessorServiceClient() + + # Initialize request argument(s) + inline_document = documentai_v1beta3.Document() + inline_document.uri = "uri_value" + + project = "my-project-id" + location = "us-central1" + processor = "processor_value" + human_review_config = f"projects/{project}/locations/{location}/processors/{processor}/humanReviewConfig" + + request = documentai_v1beta3.ReviewDocumentRequest( + inline_document=inline_document, + human_review_config=human_review_config, + ) + + # Make the request + operation = client.review_document(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + print(response) + +# [END documentai_generated_documentai_v1beta3_DocumentProcessorService_ReviewDocument_sync] diff --git a/samples/snippets/batch_process_documents_sample.py b/samples/snippets/batch_process_documents_sample.py index 88217093..d85948e7 100644 --- a/samples/snippets/batch_process_documents_sample.py +++ b/samples/snippets/batch_process_documents_sample.py @@ -63,9 +63,7 @@ def batch_process_documents( # Location can be 'us' or 'eu' name = f"projects/{project_id}/locations/{location}/processors/{processor_id}" request = documentai.types.document_processor_service.BatchProcessRequest( - name=name, - input_documents=input_config, - document_output_config=output_config, + name=name, input_documents=input_config, document_output_config=output_config, ) operation = client.batch_process_documents(request) diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index 93a9122c..3bbef5d5 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -14,6 +14,7 @@ from __future__ import print_function +import glob import os from pathlib import Path import sys @@ -184,37 +185,44 @@ def blacken(session: nox.sessions.Session) -> None: def _session_tests( session: nox.sessions.Session, post_install: Callable = None ) -> None: - if TEST_CONFIG["pip_version_override"]: - pip_version = TEST_CONFIG["pip_version_override"] - session.install(f"pip=={pip_version}") - """Runs py.test for a particular project.""" - if os.path.exists("requirements.txt"): - if os.path.exists("constraints.txt"): - session.install("-r", "requirements.txt", "-c", "constraints.txt") - else: - session.install("-r", "requirements.txt") - - if os.path.exists("requirements-test.txt"): - if os.path.exists("constraints-test.txt"): - session.install("-r", "requirements-test.txt", "-c", "constraints-test.txt") - else: - session.install("-r", "requirements-test.txt") - - if INSTALL_LIBRARY_FROM_SOURCE: - session.install("-e", _get_repo_root()) - - if post_install: - post_install(session) - - session.run( - "pytest", - *(PYTEST_COMMON_ARGS + session.posargs), - # Pytest will return 5 when no tests are collected. This can happen - # on travis where slow and flaky tests are excluded. - # See http://doc.pytest.org/en/latest/_modules/_pytest/main.html - success_codes=[0, 5], - env=get_pytest_env_vars(), - ) + # check for presence of tests + test_list = glob.glob("*_test.py") + glob.glob("test_*.py") + if len(test_list) == 0: + print("No tests found, skipping directory.") + else: + if TEST_CONFIG["pip_version_override"]: + pip_version = TEST_CONFIG["pip_version_override"] + session.install(f"pip=={pip_version}") + """Runs py.test for a particular project.""" + if os.path.exists("requirements.txt"): + if os.path.exists("constraints.txt"): + session.install("-r", "requirements.txt", "-c", "constraints.txt") + else: + session.install("-r", "requirements.txt") + + if os.path.exists("requirements-test.txt"): + if os.path.exists("constraints-test.txt"): + session.install( + "-r", "requirements-test.txt", "-c", "constraints-test.txt" + ) + else: + session.install("-r", "requirements-test.txt") + + if INSTALL_LIBRARY_FROM_SOURCE: + session.install("-e", _get_repo_root()) + + if post_install: + post_install(session) + + session.run( + "pytest", + *(PYTEST_COMMON_ARGS + session.posargs), + # Pytest will return 5 when no tests are collected. This can happen + # on travis where slow and flaky tests are excluded. + # See http://doc.pytest.org/en/latest/_modules/_pytest/main.html + success_codes=[0, 5], + env=get_pytest_env_vars(), + ) @nox.session(python=ALL_VERSIONS) diff --git a/samples/snippets/process_document_form_sample.py b/samples/snippets/process_document_form_sample.py new file mode 100644 index 00000000..06e3d242 --- /dev/null +++ b/samples/snippets/process_document_form_sample.py @@ -0,0 +1,116 @@ +# 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. +# + +# [START documentai_process_form_document] + +# TODO(developer): Uncomment these variables before running the sample. +# project_id= 'YOUR_PROJECT_ID' +# location = 'YOUR_PROJECT_LOCATION' # Format is 'us' or 'eu' +# processor_id = 'YOUR_PROCESSOR_ID' # Create processor in Cloud Console +# file_path = '/path/to/local/pdf' + + +def process_document_form_sample( + project_id: str, location: str, processor_id: str, file_path: str +): + from google.cloud import documentai_v1beta3 as documentai + + # You must set the api_endpoint if you use a location other than 'us', e.g.: + opts = {} + if location == "eu": + opts = {"api_endpoint": "eu-documentai.googleapis.com"} + + client = documentai.DocumentProcessorServiceClient(client_options=opts) + + # The full resource name of the processor, e.g.: + # projects/project-id/locations/location/processor/processor-id + # You must create new processors in the Cloud Console first + name = f"projects/{project_id}/locations/{location}/processors/{processor_id}" + + with open(file_path, "rb") as image: + image_content = image.read() + + # Read the file into memory + document = {"content": image_content, "mime_type": "application/pdf"} + + # Configure the process request + request = {"name": name, "raw_document": document} + + # Recognizes text entities in the PDF document + result = client.process_document(request=request) + + print("Document processing complete.") + + # Read the table and form fields output from the processor + # The form processor also contains OCR data. For more information + # on how to parse OCR data please see the OCR sample. + # For a full list of Document object attributes, please reference this page: https://googleapis.dev/python/documentai/latest/_modules/google/cloud/documentai_v1beta3/types/document.html#Document + document = result.document + text = document.text + print(f"Full document text: {repr(text)}\n") + print(f"There are {len(document.pages)} page(s) in this document.") + + # Read the text recognition output from the processor + for page in document.pages: + print(f"\n\n**** Page {page.page_number} ****") + + print(f"Found {len(page.tables)} table(s):") + for table in page.tables: + num_collumns = len(table.header_rows[0].cells) + num_rows = len(table.body_rows) + print(f"Table with {num_collumns} columns and {num_rows} rows:") + print_table_info(table, text) + print(f"Found {len(page.form_fields)} form fields:") + for field in page.form_fields: + name = layout_to_text(field.field_name, text) + value = layout_to_text(field.field_value, text) + print(f" * {repr(name.strip())}: {repr(value.strip())}") + + +def print_table_info(table: dict, text: str) -> None: + # Print header row + header_row_text = "" + for header_cell in table.header_rows[0].cells: + header_cell_text = layout_to_text(header_cell.layout, text) + header_row_text += f"{repr(header_cell_text.strip())} | " + print(f"Collumns: {header_row_text[:-3]}") + # Print first body row + body_row_text = "" + for body_cell in table.body_rows[0].cells: + body_cell_text = layout_to_text(body_cell.layout, text) + body_row_text += f"{repr(body_cell_text.strip())} | " + print(f"First row data: {body_row_text[:-3]}\n") + + +def layout_to_text(layout: dict, text: str) -> str: + """ + Document AI identifies form fields by their offsets in the entirity of the + document's text. This function converts offsets to a string. + """ + response = "" + # If a text segment spans several lines, it will + # be stored in different text segments. + for segment in layout.text_anchor.text_segments: + start_index = ( + int(segment.start_index) + if segment in layout.text_anchor.text_segments + else 0 + ) + end_index = int(segment.end_index) + response += text[start_index:end_index] + return response + + +# [END documentai_process_form_document] diff --git a/samples/snippets/process_document_form_sample_test.py b/samples/snippets/process_document_form_sample_test.py new file mode 100644 index 00000000..da76d6d0 --- /dev/null +++ b/samples/snippets/process_document_form_sample_test.py @@ -0,0 +1,43 @@ +# # 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. +# + +import os + +from samples.snippets import process_document_form_sample + + +location = "us" +project_id = os.environ["GOOGLE_CLOUD_PROJECT"] +processor_id = "90484cfdedb024f6" +file_path = "resources/invoice.pdf" + + +def test_process_documents(capsys): + process_document_form_sample.process_document_form_sample( + project_id=project_id, + location=location, + processor_id=processor_id, + file_path=file_path, + ) + out, _ = capsys.readouterr() + + expected_strings = [ + "There are 1 page(s) in this document.", + "Table with 4 columns and 6 rows", + "Found 13 form fields", + "'BALANCE DUE': '$2140.00'", + ] + for expected_string in expected_strings: + assert expected_string in out diff --git a/samples/snippets/process_document_ocr_sample.py b/samples/snippets/process_document_ocr_sample.py new file mode 100644 index 00000000..92718080 --- /dev/null +++ b/samples/snippets/process_document_ocr_sample.py @@ -0,0 +1,142 @@ +# 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. +# + +# [START documentai_process_ocr_document] + +# TODO(developer): Uncomment these variables before running the sample. +# project_id= 'YOUR_PROJECT_ID' +# location = 'YOUR_PROJECT_LOCATION' # Format is 'us' or 'eu' +# processor_id = 'YOUR_PROCESSOR_ID' # Create processor in Cloud Console +# file_path = '/path/to/local/pdf' + + +def process_document_ocr_sample( + project_id: str, location: str, processor_id: str, file_path: str +) -> None: + from google.cloud import documentai_v1beta3 as documentai + + # You must set the api_endpoint if you use a location other than 'us', e.g.: + opts = {} + if location == "eu": + opts = {"api_endpoint": "eu-documentai.googleapis.com"} + + client = documentai.DocumentProcessorServiceClient(client_options=opts) + + # The full resource name of the processor, e.g.: + # projects/project-id/locations/location/processor/processor-id + # You must create new processors in the Cloud Console first + name = f"projects/{project_id}/locations/{location}/processors/{processor_id}" + + with open(file_path, "rb") as image: + image_content = image.read() + + # Read the file into memory + document = {"content": image_content, "mime_type": "application/pdf"} + + # Configure the process request + request = {"name": name, "raw_document": document} + + # Recognizes text entities in the PDF document + result = client.process_document(request=request) + + print("Document processing complete.") + + # Read the text recognition output from the processor + # For a full list of Document object attributes, please reference this page: https://googleapis.dev/python/documentai/latest/_modules/google/cloud/documentai_v1beta3/types/document.html#Document + document = result.document + text = document.text + print(f"Full document text: {repr(text)}\n") + print(f"There are {len(document.pages)} page(s) in this document.\n") + + for page in document.pages: + print(f"Page {page.page_number}:") + print_page_dimensions(page.dimension) + print_detected_langauges(page.detected_languages) + print_paragraphs(page.paragraphs, text) + print_blocks(page.blocks, text) + print_lines(page.lines, text) + print_tokens(page.tokens, text) + + +def print_page_dimensions(dimension: dict) -> None: + print(f" Width: {str(dimension.width)}") + print(f" Height: {str(dimension.height)}") + + +def print_detected_langauges(detected_languages: dict) -> None: + print(" Detected languages:") + for lang in detected_languages: + code = lang.language_code + conf_percent = "{:.1%}".format(lang.confidence) + print(f" {code} ({conf_percent} confidence)") + + +def print_paragraphs(paragraphs: dict, text: str) -> None: + print(f" {len(paragraphs)} paragraphs detected:") + first_paragraph_text = layout_to_text(paragraphs[0].layout, text) + print(f" First paragraph text: {repr(first_paragraph_text)}") + last_paragraph_text = layout_to_text(paragraphs[-1].layout, text) + print(f" Last paragraph text: {repr(last_paragraph_text)}") + + +def print_blocks(blocks: dict, text: str) -> None: + print(f" {len(blocks)} blocks detected:") + first_block_text = layout_to_text(blocks[0].layout, text) + print(f" First text block: {repr(first_block_text)}") + last_block_text = layout_to_text(blocks[-1].layout, text) + print(f" Last text block: {repr(last_block_text)}") + + +def print_lines(lines: dict, text: str) -> None: + print(f" {len(lines)} lines detected:") + first_line_text = layout_to_text(lines[0].layout, text) + print(f" First line text: {repr(first_line_text)}") + last_line_text = layout_to_text(lines[-1].layout, text) + print(f" Last line text: {repr(last_line_text)}") + + +def print_tokens(tokens: dict, text: str) -> None: + print(f" {len(tokens)} tokens detected:") + first_token_text = layout_to_text(tokens[0].layout, text) + first_token_break_type = tokens[0].detected_break.type_.name + print(f" First token text: {repr(first_token_text)}") + print(f" First token break type: {repr(first_token_break_type)}") + last_token_text = layout_to_text(tokens[-1].layout, text) + last_token_break_type = tokens[-1].detected_break.type_.name + print(f" Last token text: {repr(last_token_text)}") + print(f" Last token break type: {repr(last_token_break_type)}") + + +def layout_to_text(layout: dict, text: str) -> str: + """ + Document AI identifies text in different parts of the document by their + offsets in the entirity of the document's text. This function converts + offsets to a string. + """ + response = "" + # If a text segment spans several lines, it will + # be stored in different text segments. + for segment in layout.text_anchor.text_segments: + start_index = ( + int(segment.start_index) + if segment in layout.text_anchor.text_segments + else 0 + ) + end_index = int(segment.end_index) + response += text[start_index:end_index] + return response + + +# [END documentai_process_ocr_document] diff --git a/samples/snippets/process_document_ocr_sample_test.py b/samples/snippets/process_document_ocr_sample_test.py new file mode 100644 index 00000000..f18dd2a5 --- /dev/null +++ b/samples/snippets/process_document_ocr_sample_test.py @@ -0,0 +1,37 @@ +# # 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. +# + +import os + +from samples.snippets import process_document_ocr_sample + +location = "us" +project_id = os.environ["GOOGLE_CLOUD_PROJECT"] +processor_id = "91e072f8626a76b7" +file_path = "resources/handwritten_form.pdf" + + +def test_process_documents(capsys): + process_document_ocr_sample.process_document_ocr_sample( + project_id=project_id, + location=location, + processor_id=processor_id, + file_path=file_path, + ) + out, _ = capsys.readouterr() + + assert "Page 1" in out + assert "en" in out + assert "FakeDoc" in out diff --git a/samples/snippets/process_document_quality_sample.py b/samples/snippets/process_document_quality_sample.py new file mode 100644 index 00000000..ec92c82c --- /dev/null +++ b/samples/snippets/process_document_quality_sample.py @@ -0,0 +1,78 @@ +# 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. +# + +# [START documentai_process_quality_document] + +# TODO(developer): Uncomment these variables before running the sample. +# project_id= 'YOUR_PROJECT_ID' +# location = 'YOUR_PROJECT_LOCATION' # Format is 'us' or 'eu' +# processor_id = 'YOUR_PROCESSOR_ID' # Create processor in Cloud Console +# file_path = '/path/to/local/pdf' + + +def process_document_quality_sample( + project_id: str, location: str, processor_id: str, file_path: str +): + from google.cloud import documentai_v1beta3 as documentai + + # You must set the api_endpoint if you use a location other than 'us', e.g.: + opts = {} + if location == "eu": + opts = {"api_endpoint": "eu-documentai.googleapis.com"} + + client = documentai.DocumentProcessorServiceClient(client_options=opts) + + # The full resource name of the processor, e.g.: + # projects/project-id/locations/location/processor/processor-id + # You must create new processors in the Cloud Console first + name = f"projects/{project_id}/locations/{location}/processors/{processor_id}" + + with open(file_path, "rb") as image: + image_content = image.read() + + # Read the file into memory + document = {"content": image_content, "mime_type": "application/pdf"} + + # Configure the process request + request = {"name": name, "raw_document": document} + + # Recognizes text entities in the PDF document + result = client.process_document(request=request) + + print("Document processing complete.\n") + + # Read the quality-specific information from the output from the + # Intelligent Document Quality Processor: + # https://cloud.google.com/document-ai/docs/processors-list#processor_doc-quality-processor + # OCR and other data is also present in the quality processor's response. + # Please see the OCR and other samples for how to parse other data in the + # response. + document = result.document + for entity in document.entities: + conf_percent = "{:.1%}".format(entity.confidence) + page_num = "" + try: + page_num = str(int(entity.page_anchor.page_refs.page) + 1) + except AttributeError: + page_num = "1" + + print(f"Page {page_num} has a quality score of {conf_percent}:") + + for prop in entity.properties: + conf_percent = "{:.1%}".format(prop.confidence) + print(f" * {prop.type_} score of {conf_percent}") + + +# [END documentai_process_quality_document] diff --git a/samples/snippets/process_document_quality_sample_test.py b/samples/snippets/process_document_quality_sample_test.py new file mode 100644 index 00000000..b025756e --- /dev/null +++ b/samples/snippets/process_document_quality_sample_test.py @@ -0,0 +1,42 @@ +# # 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. +# + +import os + +from samples.snippets import process_document_quality_sample + + +location = "us" +project_id = os.environ["GOOGLE_CLOUD_PROJECT"] +processor_id = "7fcb597c523721b3" +poor_quality_file_path = "resources/document_quality_poor.pdf" + + +def test_process_documents(capsys): + process_document_quality_sample.process_document_quality_sample( + project_id=project_id, + location=location, + processor_id=processor_id, + file_path=poor_quality_file_path, + ) + out, _ = capsys.readouterr() + + expected_strings = [ + "Page 1 has a quality score of", + "defect_blurry score of 9", + "defect_noisy", + ] + for expected_string in expected_strings: + assert expected_string in out diff --git a/samples/snippets/process_document_specialized_sample.py b/samples/snippets/process_document_specialized_sample.py new file mode 100644 index 00000000..e30b9517 --- /dev/null +++ b/samples/snippets/process_document_specialized_sample.py @@ -0,0 +1,79 @@ +# 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. +# + +# [START documentai_process_specialized_document] + +# TODO(developer): Uncomment these variables before running the sample. +# project_id= 'YOUR_PROJECT_ID' +# location = 'YOUR_PROJECT_LOCATION' # Format is 'us' or 'eu' +# processor_id = 'YOUR_PROCESSOR_ID' # Create processor in Cloud Console +# file_path = '/path/to/local/pdf' + + +def process_document_specialized_sample( + project_id: str, location: str, processor_id: str, file_path: str +): + from google.cloud import documentai_v1beta3 as documentai + + # You must set the api_endpoint if you use a location other than 'us', e.g.: + opts = {} + if location == "eu": + opts = {"api_endpoint": "eu-documentai.googleapis.com"} + + client = documentai.DocumentProcessorServiceClient(client_options=opts) + + # The full resource name of the processor, e.g.: + # projects/project-id/locations/location/processor/processor-id + # You must create new processors in the Cloud Console first + name = f"projects/{project_id}/locations/{location}/processors/{processor_id}" + + with open(file_path, "rb") as image: + image_content = image.read() + + # Read the file into memory + document = {"content": image_content, "mime_type": "application/pdf"} + + # Configure the process request + request = {"name": name, "raw_document": document} + + # Recognizes text entities in the PDF document + result = client.process_document(request=request) + + print("Document processing complete.\n") + + # Read fields specificly from the specalized US drivers license processor: + # https://cloud.google.com/document-ai/docs/processors-list#processor_us-driver-license-parser + # retriving data from other specalized processors follow a similar pattern. + # For a complete list of processors see: + # https://cloud.google.com/document-ai/docs/processors-list + # + # OCR and other data is also present in the quality processor's response. + # Please see the OCR and other samples for how to parse other data in the + # response. + document = result.document + print(f"Found {len(document.entities)} entities:") + for entity in document.entities: + # Fields detected. For a full list of fields for each processor see + # the processor documentation: + # https://cloud.google.com/document-ai/docs/processors-list + key = entity.type_ + # some other value formats in addition to text are availible + # e.g. dates: `entity.normalized_value.date_value.year` + text_value = entity.text_anchor.content + conf_percent = "{:.1%}".format(entity.confidence) + print(f" * {repr(key)}: {repr(text_value)}({conf_percent} confident)") + + +# [END documentai_process_specialized_document] diff --git a/samples/snippets/process_document_specialized_sample_test.py b/samples/snippets/process_document_specialized_sample_test.py new file mode 100644 index 00000000..04a7abec --- /dev/null +++ b/samples/snippets/process_document_specialized_sample_test.py @@ -0,0 +1,41 @@ +# # 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. +# + +import os + +from samples.snippets import process_document_specialized_sample + + +location = "us" +project_id = os.environ["GOOGLE_CLOUD_PROJECT"] +processor_id = "feacd98c28866ede" +file_path = "resources/us_driver_license.pdf" + + +def test_process_documents(capsys): + process_document_specialized_sample.process_document_specialized_sample( + project_id=project_id, + location=location, + processor_id=processor_id, + file_path=file_path, + ) + out, _ = capsys.readouterr() + + expected_strings = [ + "Document Id", + "97551579", + ] + for expected_string in expected_strings: + assert expected_string in out diff --git a/samples/snippets/process_document_splitter_sample.py b/samples/snippets/process_document_splitter_sample.py new file mode 100644 index 00000000..95607854 --- /dev/null +++ b/samples/snippets/process_document_splitter_sample.py @@ -0,0 +1,88 @@ +# 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. +# + +# [START documentai_process_splitter_document] + +# TODO(developer): Uncomment these variables before running the sample. +# project_id= 'YOUR_PROJECT_ID' +# location = 'YOUR_PROJECT_LOCATION' # Format is 'us' or 'eu' +# processor_id = 'YOUR_PROCESSOR_ID' # Create processor in Cloud Console +# file_path = '/path/to/local/pdf' + + +def process_document_splitter_sample( + project_id: str, location: str, processor_id: str, file_path: str +): + from google.cloud import documentai_v1beta3 as documentai + + # You must set the api_endpoint if you use a location other than 'us', e.g.: + opts = {} + if location == "eu": + opts = {"api_endpoint": "eu-documentai.googleapis.com"} + + client = documentai.DocumentProcessorServiceClient(client_options=opts) + + # The full resource name of the processor, e.g.: + # projects/project-id/locations/location/processor/processor-id + # You must create new processors in the Cloud Console first + name = f"projects/{project_id}/locations/{location}/processors/{processor_id}" + + with open(file_path, "rb") as image: + image_content = image.read() + + # Read the file into memory + document = {"content": image_content, "mime_type": "application/pdf"} + + # Configure the process request + request = {"name": name, "raw_document": document} + + # Recognizes text entities in the PDF document + result = client.process_document(request=request) + + print("Document processing complete.\n") + + # Read the splitter output from the document splitter processor: + # https://cloud.google.com/document-ai/docs/processors-list#processor_doc-splitter + # This processor only provides text for the document and information on how + # to split the document on logical boundaries. To identify and extract text, + # form elements, and entities please see other processors like the OCR, form, + # and specalized processors. + document = result.document + print(f"Found {len(document.entities)} subdocuments:") + for entity in document.entities: + conf_percent = "{:.1%}".format(entity.confidence) + pages_range = page_refs_to_string(entity.page_anchor.page_refs) + # Print subdocument type information, if available + try: + doctype = entity.type + print( + f'{conf_percent} confident that {pages_range} a "{doctype}" subdocument.' + ) + except AttributeError: + print(f"{conf_percent} confident that {pages_range} a subdocument.") + + +def page_refs_to_string(page_refs: dict) -> str: + """ Converts a page ref to a string describing the page or page range.""" + if len(page_refs) == 1: + num = str(int(page_refs[0].page) + 1) + return f"page {num} is" + else: + start = str(int(page_refs[0].page) + 1) + end = str(int(page_refs[1].page) + 1) + return f"pages {start} to {end} are" + + +# [END documentai_process_splitter_document] diff --git a/samples/snippets/process_document_splitter_sample_test.py b/samples/snippets/process_document_splitter_sample_test.py new file mode 100644 index 00000000..81f32905 --- /dev/null +++ b/samples/snippets/process_document_splitter_sample_test.py @@ -0,0 +1,42 @@ +# # 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. +# + +import os + +from samples.snippets import process_document_splitter_sample + + +location = "us" +project_id = os.environ["GOOGLE_CLOUD_PROJECT"] +processor_id = "ed55eeb2b276066f" +file_path = "resources/multi_document.pdf" + + +def test_process_documents(capsys): + process_document_splitter_sample.process_document_splitter_sample( + project_id=project_id, + location=location, + processor_id=processor_id, + file_path=file_path, + ) + out, _ = capsys.readouterr() + + expected_strings = [ + "Found 8 subdocuments", + "confident that pages 1 to 2 are a subdocument", + "confident that page 10 is a subdocument", + ] + for expected_string in expected_strings: + assert expected_string in out diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index 0ca6f641..16658b4a 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1,2 +1,2 @@ -google-cloud-documentai==1.1.0 -google-cloud-storage==1.42.3 +google-cloud-documentai==1.2.0 +google-cloud-storage==2.0.0 diff --git a/samples/snippets/resources/document_quality_poor.pdf b/samples/snippets/resources/document_quality_poor.pdf new file mode 100644 index 00000000..3a34a925 Binary files /dev/null and b/samples/snippets/resources/document_quality_poor.pdf differ diff --git a/samples/snippets/resources/handwritten_form.pdf b/samples/snippets/resources/handwritten_form.pdf new file mode 100644 index 00000000..2189ffff Binary files /dev/null and b/samples/snippets/resources/handwritten_form.pdf differ diff --git a/samples/snippets/resources/multi_document.pdf b/samples/snippets/resources/multi_document.pdf new file mode 100644 index 00000000..7ea62eb8 Binary files /dev/null and b/samples/snippets/resources/multi_document.pdf differ diff --git a/samples/snippets/resources/us_driver_license.pdf b/samples/snippets/resources/us_driver_license.pdf new file mode 100644 index 00000000..f8f62d90 Binary files /dev/null and b/samples/snippets/resources/us_driver_license.pdf differ diff --git a/scripts/fixup_documentai_v1_keywords.py b/scripts/fixup_documentai_v1_keywords.py new file mode 100644 index 00000000..e296b746 --- /dev/null +++ b/scripts/fixup_documentai_v1_keywords.py @@ -0,0 +1,178 @@ +#! /usr/bin/env python3 +# -*- 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. +# +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class documentaiCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'batch_process_documents': ('name', 'input_documents', 'document_output_config', 'skip_human_review', ), + 'process_document': ('name', 'inline_document', 'raw_document', 'skip_human_review', ), + 'review_document': ('human_review_config', 'inline_document', 'enable_schema_validation', 'priority', ), + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: a.keyword.value not in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), +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 + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=documentaiCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the documentai client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/scripts/fixup_documentai_v1beta2_keywords.py b/scripts/fixup_documentai_v1beta2_keywords.py new file mode 100644 index 00000000..edc0fbd2 --- /dev/null +++ b/scripts/fixup_documentai_v1beta2_keywords.py @@ -0,0 +1,177 @@ +#! /usr/bin/env python3 +# -*- 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. +# +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class documentaiCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'batch_process_documents': ('requests', 'parent', ), + 'process_document': ('input_config', 'parent', 'output_config', 'document_type', 'table_extraction_params', 'form_extraction_params', 'entity_extraction_params', 'ocr_params', 'automl_params', ), + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: a.keyword.value not in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), +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 + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=documentaiCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the documentai client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/scripts/fixup_documentai_v1beta3_keywords.py b/scripts/fixup_documentai_v1beta3_keywords.py new file mode 100644 index 00000000..74059427 --- /dev/null +++ b/scripts/fixup_documentai_v1beta3_keywords.py @@ -0,0 +1,184 @@ +#! /usr/bin/env python3 +# -*- 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. +# +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class documentaiCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'batch_process_documents': ('name', 'input_configs', 'output_config', 'input_documents', 'document_output_config', 'skip_human_review', ), + 'create_processor': ('parent', 'processor', ), + 'delete_processor': ('name', ), + 'disable_processor': ('name', ), + 'enable_processor': ('name', ), + 'fetch_processor_types': ('parent', ), + 'list_processors': ('parent', 'page_size', 'page_token', ), + 'process_document': ('name', 'inline_document', 'raw_document', 'document', 'skip_human_review', ), + 'review_document': ('human_review_config', 'inline_document', 'document', 'enable_schema_validation', 'priority', ), + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: a.keyword.value not in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), +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 + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=documentaiCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the documentai client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/setup.py b/setup.py index e9602ff5..10a9359d 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ import os import setuptools # type: ignore -version = "1.2.0" +version = "1.2.1" package_root = os.path.abspath(os.path.dirname(__file__)) @@ -48,9 +48,8 @@ # NOTE: Maintainers, please do not require google-api-core>=2.x.x # Until this issue is closed # https://github.com/googleapis/google-cloud-python/issues/10566 - "google-api-core[grpc] >= 1.26.0, <3.0.0dev", + "google-api-core[grpc] >= 1.28.0, <3.0.0dev", "proto-plus >= 1.10.0", - "packaging >= 14.3", ), python_requires=">=3.6", setup_requires=["libcst >= 0.2.5"], diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index 63d16e7e..da8c5737 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -5,7 +5,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.26.0 +google-api-core==1.28.0 proto-plus==1.10.0 -packaging==14.3 -google-auth==1.24.0 # TODO: remove when google-auth>=1.25.0 is required through google-api-core diff --git a/tests/unit/gapic/documentai_v1/test_document_processor_service.py b/tests/unit/gapic/documentai_v1/test_document_processor_service.py index 14c874fa..a4e384ed 100644 --- a/tests/unit/gapic/documentai_v1/test_document_processor_service.py +++ b/tests/unit/gapic/documentai_v1/test_document_processor_service.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -42,9 +41,6 @@ DocumentProcessorServiceClient, ) from google.cloud.documentai_v1.services.document_processor_service import transports -from google.cloud.documentai_v1.services.document_processor_service.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.documentai_v1.types import document from google.cloud.documentai_v1.types import document_io from google.cloud.documentai_v1.types import document_processor_service @@ -64,20 +60,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the 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", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -245,7 +227,7 @@ def test_document_processor_service_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +244,7 @@ def test_document_processor_service_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -279,7 +261,7 @@ def test_document_processor_service_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -295,20 +277,20 @@ def test_document_processor_service_client_client_options( # unsupported value. with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): with pytest.raises(MutualTLSChannelError): - client = client_class() + client = client_class(transport=transport_name) # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. with mock.patch.dict( os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} ): with pytest.raises(ValueError): - client = client_class() + client = client_class(transport=transport_name) # Check the case quota_project_id is provided options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -377,7 +359,7 @@ def test_document_processor_service_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) if use_client_cert_env == "false": expected_client_cert_source = None @@ -419,7 +401,7 @@ def test_document_processor_service_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -441,7 +423,7 @@ def test_document_processor_service_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -476,7 +458,7 @@ def test_document_processor_service_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -511,7 +493,7 @@ def test_document_processor_service_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -544,9 +526,10 @@ def test_document_processor_service_client_client_options_from_dict(): ) -def test_process_document( - transport: str = "grpc", request_type=document_processor_service.ProcessRequest -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.ProcessRequest, dict,] +) +def test_process_document(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -570,10 +553,6 @@ def test_process_document( assert isinstance(response, document_processor_service.ProcessResponse) -def test_process_document_from_dict(): - test_process_document(request_type=dict) - - def test_process_document_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. @@ -696,7 +675,9 @@ def test_process_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_process_document_flattened_error(): @@ -734,7 +715,9 @@ async def test_process_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -751,9 +734,10 @@ async def test_process_document_flattened_error_async(): ) -def test_batch_process_documents( - transport: str = "grpc", request_type=document_processor_service.BatchProcessRequest -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.BatchProcessRequest, dict,] +) +def test_batch_process_documents(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -779,10 +763,6 @@ def test_batch_process_documents( assert isinstance(response, future.Future) -def test_batch_process_documents_from_dict(): - test_batch_process_documents(request_type=dict) - - def test_batch_process_documents_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. @@ -915,7 +895,9 @@ def test_batch_process_documents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_batch_process_documents_flattened_error(): @@ -955,7 +937,9 @@ async def test_batch_process_documents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -972,10 +956,10 @@ async def test_batch_process_documents_flattened_error_async(): ) -def test_review_document( - transport: str = "grpc", - request_type=document_processor_service.ReviewDocumentRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.ReviewDocumentRequest, dict,] +) +def test_review_document(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -999,10 +983,6 @@ def test_review_document( assert isinstance(response, future.Future) -def test_review_document_from_dict(): - test_review_document(request_type=dict) - - def test_review_document_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. @@ -1131,7 +1111,9 @@ def test_review_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].human_review_config == "human_review_config_value" + arg = args[0].human_review_config + mock_val = "human_review_config_value" + assert arg == mock_val def test_review_document_flattened_error(): @@ -1172,7 +1154,9 @@ async def test_review_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].human_review_config == "human_review_config_value" + arg = args[0].human_review_config + mock_val = "human_review_config_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1308,7 +1292,6 @@ def test_document_processor_service_base_transport(): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_document_processor_service_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1329,26 +1312,6 @@ def test_document_processor_service_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_document_processor_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.documentai_v1.services.document_processor_service.transports.DocumentProcessorServiceTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.DocumentProcessorServiceTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=("https://www.googleapis.com/auth/cloud-platform",), - quota_project_id="octopus", - ) - - def test_document_processor_service_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1360,7 +1323,6 @@ def test_document_processor_service_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_document_processor_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1373,18 +1335,6 @@ def test_document_processor_service_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_document_processor_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) - DocumentProcessorServiceClient() - adc.assert_called_once_with( - scopes=("https://www.googleapis.com/auth/cloud-platform",), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1392,7 +1342,6 @@ def test_document_processor_service_auth_adc_old_google_auth(): transports.DocumentProcessorServiceGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_document_processor_service_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1406,26 +1355,6 @@ def test_document_processor_service_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.DocumentProcessorServiceGrpcTransport, - transports.DocumentProcessorServiceGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_document_processor_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", [ @@ -1826,7 +1755,7 @@ def test_parse_common_location_path(): assert expected == actual -def test_client_withDEFAULT_CLIENT_INFO(): +def test_client_with_default_client_info(): client_info = gapic_v1.client_info.ClientInfo() with mock.patch.object( diff --git a/tests/unit/gapic/documentai_v1beta2/test_document_understanding_service.py b/tests/unit/gapic/documentai_v1beta2/test_document_understanding_service.py index 6aa3f59c..4d9c59ec 100644 --- a/tests/unit/gapic/documentai_v1beta2/test_document_understanding_service.py +++ b/tests/unit/gapic/documentai_v1beta2/test_document_understanding_service.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -44,9 +43,6 @@ from google.cloud.documentai_v1beta2.services.document_understanding_service import ( transports, ) -from google.cloud.documentai_v1beta2.services.document_understanding_service.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.documentai_v1beta2.types import document from google.cloud.documentai_v1beta2.types import document_understanding from google.cloud.documentai_v1beta2.types import geometry @@ -56,20 +52,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the 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", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -239,7 +221,7 @@ def test_document_understanding_service_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -256,7 +238,7 @@ def test_document_understanding_service_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -273,7 +255,7 @@ def test_document_understanding_service_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -289,20 +271,20 @@ def test_document_understanding_service_client_client_options( # unsupported value. with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): with pytest.raises(MutualTLSChannelError): - client = client_class() + client = client_class(transport=transport_name) # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. with mock.patch.dict( os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} ): with pytest.raises(ValueError): - client = client_class() + client = client_class(transport=transport_name) # Check the case quota_project_id is provided options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -371,7 +353,7 @@ def test_document_understanding_service_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) if use_client_cert_env == "false": expected_client_cert_source = None @@ -413,7 +395,7 @@ def test_document_understanding_service_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -435,7 +417,7 @@ def test_document_understanding_service_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -470,7 +452,7 @@ def test_document_understanding_service_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -505,7 +487,7 @@ def test_document_understanding_service_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -538,10 +520,10 @@ def test_document_understanding_service_client_client_options_from_dict(): ) -def test_batch_process_documents( - transport: str = "grpc", - request_type=document_understanding.BatchProcessDocumentsRequest, -): +@pytest.mark.parametrize( + "request_type", [document_understanding.BatchProcessDocumentsRequest, dict,] +) +def test_batch_process_documents(request_type, transport: str = "grpc"): client = DocumentUnderstandingServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -567,10 +549,6 @@ def test_batch_process_documents( assert isinstance(response, future.Future) -def test_batch_process_documents_from_dict(): - test_batch_process_documents(request_type=dict) - - def test_batch_process_documents_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. @@ -707,9 +685,11 @@ def test_batch_process_documents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].requests == [ + arg = args[0].requests + mock_val = [ document_understanding.ProcessDocumentRequest(parent="parent_value") ] + assert arg == mock_val def test_batch_process_documents_flattened_error(): @@ -756,9 +736,11 @@ async def test_batch_process_documents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].requests == [ + arg = args[0].requests + mock_val = [ document_understanding.ProcessDocumentRequest(parent="parent_value") ] + assert arg == mock_val @pytest.mark.asyncio @@ -778,9 +760,10 @@ async def test_batch_process_documents_flattened_error_async(): ) -def test_process_document( - transport: str = "grpc", request_type=document_understanding.ProcessDocumentRequest -): +@pytest.mark.parametrize( + "request_type", [document_understanding.ProcessDocumentRequest, dict,] +) +def test_process_document(request_type, transport: str = "grpc"): client = DocumentUnderstandingServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -808,10 +791,6 @@ def test_process_document( assert response.text == "text_value" -def test_process_document_from_dict(): - test_process_document(request_type=dict) - - def test_process_document_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. @@ -1034,7 +1013,6 @@ def test_document_understanding_service_base_transport(): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_document_understanding_service_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1055,26 +1033,6 @@ def test_document_understanding_service_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_document_understanding_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.documentai_v1beta2.services.document_understanding_service.transports.DocumentUnderstandingServiceTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.DocumentUnderstandingServiceTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=("https://www.googleapis.com/auth/cloud-platform",), - quota_project_id="octopus", - ) - - def test_document_understanding_service_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1086,7 +1044,6 @@ def test_document_understanding_service_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_document_understanding_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1099,18 +1056,6 @@ def test_document_understanding_service_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_document_understanding_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) - DocumentUnderstandingServiceClient() - adc.assert_called_once_with( - scopes=("https://www.googleapis.com/auth/cloud-platform",), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1118,7 +1063,6 @@ def test_document_understanding_service_auth_adc_old_google_auth(): transports.DocumentUnderstandingServiceGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_document_understanding_service_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1132,28 +1076,6 @@ def test_document_understanding_service_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.DocumentUnderstandingServiceGrpcTransport, - transports.DocumentUnderstandingServiceGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_document_understanding_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", [ @@ -1511,7 +1433,7 @@ def test_parse_common_location_path(): assert expected == actual -def test_client_withDEFAULT_CLIENT_INFO(): +def test_client_with_default_client_info(): client_info = gapic_v1.client_info.ClientInfo() with mock.patch.object( diff --git a/tests/unit/gapic/documentai_v1beta3/test_document_processor_service.py b/tests/unit/gapic/documentai_v1beta3/test_document_processor_service.py index 45746ed3..2bac0ae9 100644 --- a/tests/unit/gapic/documentai_v1beta3/test_document_processor_service.py +++ b/tests/unit/gapic/documentai_v1beta3/test_document_processor_service.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -45,9 +44,6 @@ from google.cloud.documentai_v1beta3.services.document_processor_service import ( transports, ) -from google.cloud.documentai_v1beta3.services.document_processor_service.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.documentai_v1beta3.types import document from google.cloud.documentai_v1beta3.types import document_io from google.cloud.documentai_v1beta3.types import document_processor_service @@ -70,20 +66,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the 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", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -251,7 +233,7 @@ def test_document_processor_service_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -268,7 +250,7 @@ def test_document_processor_service_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -285,7 +267,7 @@ def test_document_processor_service_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -301,20 +283,20 @@ def test_document_processor_service_client_client_options( # unsupported value. with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): with pytest.raises(MutualTLSChannelError): - client = client_class() + client = client_class(transport=transport_name) # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. with mock.patch.dict( os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} ): with pytest.raises(ValueError): - client = client_class() + client = client_class(transport=transport_name) # Check the case quota_project_id is provided options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -383,7 +365,7 @@ def test_document_processor_service_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) if use_client_cert_env == "false": expected_client_cert_source = None @@ -425,7 +407,7 @@ def test_document_processor_service_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -447,7 +429,7 @@ def test_document_processor_service_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -482,7 +464,7 @@ def test_document_processor_service_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -517,7 +499,7 @@ def test_document_processor_service_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(client_options=options, transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -550,9 +532,10 @@ def test_document_processor_service_client_client_options_from_dict(): ) -def test_process_document( - transport: str = "grpc", request_type=document_processor_service.ProcessRequest -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.ProcessRequest, dict,] +) +def test_process_document(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -579,10 +562,6 @@ def test_process_document( assert response.human_review_operation == "human_review_operation_value" -def test_process_document_from_dict(): - test_process_document(request_type=dict) - - def test_process_document_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. @@ -708,7 +687,9 @@ def test_process_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_process_document_flattened_error(): @@ -746,7 +727,9 @@ async def test_process_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -763,9 +746,10 @@ async def test_process_document_flattened_error_async(): ) -def test_batch_process_documents( - transport: str = "grpc", request_type=document_processor_service.BatchProcessRequest -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.BatchProcessRequest, dict,] +) +def test_batch_process_documents(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -791,10 +775,6 @@ def test_batch_process_documents( assert isinstance(response, future.Future) -def test_batch_process_documents_from_dict(): - test_batch_process_documents(request_type=dict) - - def test_batch_process_documents_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. @@ -927,7 +907,9 @@ def test_batch_process_documents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_batch_process_documents_flattened_error(): @@ -967,7 +949,9 @@ async def test_batch_process_documents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -984,10 +968,10 @@ async def test_batch_process_documents_flattened_error_async(): ) -def test_fetch_processor_types( - transport: str = "grpc", - request_type=document_processor_service.FetchProcessorTypesRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.FetchProcessorTypesRequest, dict,] +) +def test_fetch_processor_types(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -1013,10 +997,6 @@ def test_fetch_processor_types( assert isinstance(response, document_processor_service.FetchProcessorTypesResponse) -def test_fetch_processor_types_from_dict(): - test_fetch_processor_types(request_type=dict) - - def test_fetch_processor_types_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. @@ -1149,7 +1129,9 @@ def test_fetch_processor_types_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_fetch_processor_types_flattened_error(): @@ -1190,7 +1172,9 @@ async def test_fetch_processor_types_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1208,10 +1192,10 @@ async def test_fetch_processor_types_flattened_error_async(): ) -def test_list_processors( - transport: str = "grpc", - request_type=document_processor_service.ListProcessorsRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.ListProcessorsRequest, dict,] +) +def test_list_processors(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -1238,10 +1222,6 @@ def test_list_processors( assert response.next_page_token == "next_page_token_value" -def test_list_processors_from_dict(): - test_list_processors(request_type=dict) - - def test_list_processors_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. @@ -1367,7 +1347,9 @@ def test_list_processors_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_processors_flattened_error(): @@ -1405,7 +1387,9 @@ async def test_list_processors_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1422,9 +1406,9 @@ async def test_list_processors_flattened_error_async(): ) -def test_list_processors_pager(): +def test_list_processors_pager(transport_name: str = "grpc"): client = DocumentProcessorServiceClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials, transport=transport_name, ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1464,9 +1448,9 @@ def test_list_processors_pager(): assert all(isinstance(i, processor.Processor) for i in results) -def test_list_processors_pages(): +def test_list_processors_pages(transport_name: str = "grpc"): client = DocumentProcessorServiceClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials, transport=transport_name, ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1576,10 +1560,10 @@ async def test_list_processors_async_pages(): assert page_.raw_page.next_page_token == token -def test_create_processor( - transport: str = "grpc", - request_type=document_processor_service.CreateProcessorRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.CreateProcessorRequest, dict,] +) +def test_create_processor(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -1618,10 +1602,6 @@ def test_create_processor( assert response.kms_key_name == "kms_key_name_value" -def test_create_processor_from_dict(): - test_create_processor(request_type=dict) - - def test_create_processor_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. @@ -1761,8 +1741,12 @@ def test_create_processor_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].processor == gcd_processor.Processor(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].processor + mock_val = gcd_processor.Processor(name="name_value") + assert arg == mock_val def test_create_processor_flattened_error(): @@ -1804,8 +1788,12 @@ async def test_create_processor_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].processor == gcd_processor.Processor(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].processor + mock_val = gcd_processor.Processor(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1824,10 +1812,10 @@ async def test_create_processor_flattened_error_async(): ) -def test_delete_processor( - transport: str = "grpc", - request_type=document_processor_service.DeleteProcessorRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.DeleteProcessorRequest, dict,] +) +def test_delete_processor(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -1851,10 +1839,6 @@ def test_delete_processor( assert isinstance(response, future.Future) -def test_delete_processor_from_dict(): - test_delete_processor(request_type=dict) - - def test_delete_processor_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. @@ -1977,7 +1961,9 @@ def test_delete_processor_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_processor_flattened_error(): @@ -2015,7 +2001,9 @@ async def test_delete_processor_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2032,10 +2020,10 @@ async def test_delete_processor_flattened_error_async(): ) -def test_enable_processor( - transport: str = "grpc", - request_type=document_processor_service.EnableProcessorRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.EnableProcessorRequest, dict,] +) +def test_enable_processor(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -2059,10 +2047,6 @@ def test_enable_processor( assert isinstance(response, future.Future) -def test_enable_processor_from_dict(): - test_enable_processor(request_type=dict) - - def test_enable_processor_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. @@ -2168,10 +2152,10 @@ async def test_enable_processor_field_headers_async(): assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] -def test_disable_processor( - transport: str = "grpc", - request_type=document_processor_service.DisableProcessorRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.DisableProcessorRequest, dict,] +) +def test_disable_processor(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -2197,10 +2181,6 @@ def test_disable_processor( assert isinstance(response, future.Future) -def test_disable_processor_from_dict(): - test_disable_processor(request_type=dict) - - def test_disable_processor_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. @@ -2314,10 +2294,10 @@ async def test_disable_processor_field_headers_async(): assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] -def test_review_document( - transport: str = "grpc", - request_type=document_processor_service.ReviewDocumentRequest, -): +@pytest.mark.parametrize( + "request_type", [document_processor_service.ReviewDocumentRequest, dict,] +) +def test_review_document(request_type, transport: str = "grpc"): client = DocumentProcessorServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) @@ -2341,10 +2321,6 @@ def test_review_document( assert isinstance(response, future.Future) -def test_review_document_from_dict(): - test_review_document(request_type=dict) - - def test_review_document_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. @@ -2473,7 +2449,9 @@ def test_review_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].human_review_config == "human_review_config_value" + arg = args[0].human_review_config + mock_val = "human_review_config_value" + assert arg == mock_val def test_review_document_flattened_error(): @@ -2514,7 +2492,9 @@ async def test_review_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].human_review_config == "human_review_config_value" + arg = args[0].human_review_config + mock_val = "human_review_config_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2656,7 +2636,6 @@ def test_document_processor_service_base_transport(): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_document_processor_service_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2677,26 +2656,6 @@ def test_document_processor_service_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_document_processor_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.documentai_v1beta3.services.document_processor_service.transports.DocumentProcessorServiceTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.DocumentProcessorServiceTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=("https://www.googleapis.com/auth/cloud-platform",), - quota_project_id="octopus", - ) - - def test_document_processor_service_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2708,7 +2667,6 @@ def test_document_processor_service_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_document_processor_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2721,18 +2679,6 @@ def test_document_processor_service_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_document_processor_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) - DocumentProcessorServiceClient() - adc.assert_called_once_with( - scopes=("https://www.googleapis.com/auth/cloud-platform",), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2740,7 +2686,6 @@ def test_document_processor_service_auth_adc_old_google_auth(): transports.DocumentProcessorServiceGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_document_processor_service_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2754,26 +2699,6 @@ def test_document_processor_service_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.DocumentProcessorServiceGrpcTransport, - transports.DocumentProcessorServiceGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_document_processor_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", [ @@ -3200,7 +3125,7 @@ def test_parse_common_location_path(): assert expected == actual -def test_client_withDEFAULT_CLIENT_INFO(): +def test_client_with_default_client_info(): client_info = gapic_v1.client_info.ClientInfo() with mock.patch.object(