# -*- coding: utf-8 -*-
# Copyright 2023 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.
#
from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union
import warnings

from google.api_core import gapic_v1, grpc_helpers_async, operations_v1
from google.auth import credentials as ga_credentials  # type: ignore
from google.auth.transport.grpc import SslCredentials  # type: ignore
from google.iam.v1 import iam_policy_pb2  # type: ignore
from google.iam.v1 import policy_pb2  # type: ignore
from google.longrunning import operations_pb2  # type: ignore
from google.protobuf import empty_pb2  # type: ignore
import grpc  # type: ignore
from grpc.experimental import aio  # type: ignore

from google.cloud.datacatalog_v1.types import datacatalog, tags

from .base import DEFAULT_CLIENT_INFO, DataCatalogTransport
from .grpc import DataCatalogGrpcTransport

class DataCatalogGrpcAsyncIOTransport(DataCatalogTransport):
    """gRPC AsyncIO backend transport for DataCatalog.

    Data Catalog API service allows you to discover, understand,
    and manage your data.

    This class defines the same methods as the primary client, so the
    primary client can load the underlying transport implementation
    and call it.

    It sends protocol buffers over the wire using gRPC (which is built on
    top of HTTP/2); the ``grpcio`` package must be installed.
    """

    _grpc_channel: aio.Channel
    _stubs: Dict[str, Callable] = {}

    @classmethod
    def create_channel(
        cls,
        host: str = "datacatalog.googleapis.com",
        credentials: Optional[ga_credentials.Credentials] = None,
        credentials_file: Optional[str] = None,
        scopes: Optional[Sequence[str]] = None,
        quota_project_id: Optional[str] = None,
        **kwargs,
    ) -> aio.Channel:
        """Create and return a gRPC AsyncIO channel object.
        Args:
            host (Optional[str]): The host for the channel to use.
            credentials (Optional[~.Credentials]): The
                authorization credentials to attach to requests. These
                credentials identify this application to the service. If
                none are specified, the client will attempt to ascertain
                the credentials from the environment.
            credentials_file (Optional[str]): A file with credentials that can
                be loaded with :func:`google.auth.load_credentials_from_file`.
                This argument is ignored if ``channel`` is provided.
            scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
                service. These are only used when credentials are not specified and
                are passed to :func:`google.auth.default`.
            quota_project_id (Optional[str]): An optional project to use for billing
                and quota.
            kwargs (Optional[dict]): Keyword arguments, which are passed to the
                channel creation.
        Returns:
            aio.Channel: A gRPC AsyncIO channel object.
        """

        return grpc_helpers_async.create_channel(
            host,
            credentials=credentials,
            credentials_file=credentials_file,
            quota_project_id=quota_project_id,
            default_scopes=cls.AUTH_SCOPES,
            scopes=scopes,
            default_host=cls.DEFAULT_HOST,
            **kwargs,
        )

    def __init__(
        self,
        *,
        host: str = "datacatalog.googleapis.com",
        credentials: Optional[ga_credentials.Credentials] = None,
        credentials_file: Optional[str] = None,
        scopes: Optional[Sequence[str]] = None,
        channel: Optional[aio.Channel] = None,
        api_mtls_endpoint: Optional[str] = None,
        client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
        ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None,
        client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
        quota_project_id: Optional[str] = None,
        client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
        always_use_jwt_access: Optional[bool] = False,
        api_audience: Optional[str] = None,
    ) -> None:
        """Instantiate the transport.

        Args:
            host (Optional[str]):
                 The hostname to connect to.
            credentials (Optional[google.auth.credentials.Credentials]): The
                authorization credentials to attach to requests. These
                credentials identify the application to the service; if none
                are specified, the client will attempt to ascertain the
                credentials from the environment.
                This argument is ignored if ``channel`` is provided.
            credentials_file (Optional[str]): A file with credentials that can
                be loaded with :func:`google.auth.load_credentials_from_file`.
                This argument is ignored if ``channel`` is provided.
            scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
                service. These are only used when credentials are not specified and
                are passed to :func:`google.auth.default`.
            channel (Optional[aio.Channel]): A ``Channel`` instance through
                which to make calls.
            api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
                If provided, it overrides the ``host`` argument and tries to create
                a mutual TLS channel with client SSL credentials from
                ``client_cert_source`` or application default SSL credentials.
            client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
                Deprecated. A callback to provide client SSL certificate bytes and
                private key bytes, both in PEM format. It is ignored if
                ``api_mtls_endpoint`` is None.
            ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
                for the grpc channel. It is ignored if ``channel`` is provided.
            client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
                A callback to provide client certificate bytes and private key bytes,
                both in PEM format. It is used to configure a mutual TLS channel. It is
                ignored if ``channel`` or ``ssl_channel_credentials`` is provided.
            quota_project_id (Optional[str]): An optional project to use for billing
                and quota.
            client_info (google.api_core.gapic_v1.client_info.ClientInfo):
                The client info used to send a user-agent string along with
                API requests. If ``None``, then default info will be used.
                Generally, you only need to set this if you're developing
                your own client library.
            always_use_jwt_access (Optional[bool]): Whether self signed JWT should
                be used for service account credentials.

        Raises:
            google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
              creation failed for any reason.
          google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
              and ``credentials_file`` are passed.
        """
        self._grpc_channel = None
        self._ssl_channel_credentials = ssl_channel_credentials
        self._stubs: Dict[str, Callable] = {}
        self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None

        if api_mtls_endpoint:
            warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
        if client_cert_source:
            warnings.warn("client_cert_source is deprecated", DeprecationWarning)

        if channel:
            # Ignore credentials if a channel was passed.
            credentials = False
            # If a channel was explicitly provided, set it.
            self._grpc_channel = channel
            self._ssl_channel_credentials = None
        else:
            if api_mtls_endpoint:
                host = api_mtls_endpoint

                # Create SSL credentials with client_cert_source or application
                # default SSL credentials.
                if client_cert_source:
                    cert, key = client_cert_source()
                    self._ssl_channel_credentials = grpc.ssl_channel_credentials(
                        certificate_chain=cert, private_key=key
                    )
                else:
                    self._ssl_channel_credentials = SslCredentials().ssl_credentials

            else:
                if client_cert_source_for_mtls and not ssl_channel_credentials:
                    cert, key = client_cert_source_for_mtls()
                    self._ssl_channel_credentials = grpc.ssl_channel_credentials(
                        certificate_chain=cert, private_key=key
                    )

        # The base transport sets the host, credentials and scopes
        super().__init__(
            host=host,
            credentials=credentials,
            credentials_file=credentials_file,
            scopes=scopes,
            quota_project_id=quota_project_id,
            client_info=client_info,
            always_use_jwt_access=always_use_jwt_access,
            api_audience=api_audience,
        )

        if not self._grpc_channel:
            self._grpc_channel = type(self).create_channel(
                self._host,
                # use the credentials which are saved
                credentials=self._credentials,
                # Set ``credentials_file`` to ``None`` here as
                # the credentials that we saved earlier should be used.
                credentials_file=None,
                scopes=self._scopes,
                ssl_credentials=self._ssl_channel_credentials,
                quota_project_id=quota_project_id,
                options=[
                    ("grpc.max_send_message_length", -1),
                    ("grpc.max_receive_message_length", -1),
                ],
            )

        # Wrap messages. This must be done after self._grpc_channel exists
        self._prep_wrapped_messages(client_info)

    @property
    def grpc_channel(self) -> aio.Channel:
        """Create the channel designed to connect to this service.

        This property caches on the instance; repeated calls return
        the same channel.
        """
        # Return the channel from cache.
        return self._grpc_channel

    @property
    def operations_client(self) -> operations_v1.OperationsAsyncClient:
        """Create the client designed to process long-running operations.

        This property caches on the instance; repeated calls return the same
        client.
        """
        # Quick check: Only create a new client if we do not already have one.
        if self._operations_client is None:
            self._operations_client = operations_v1.OperationsAsyncClient(
                self.grpc_channel
            )

        # Return the client from cache.
        return self._operations_client

    @property
    def search_catalog(
        self,
    ) -> Callable[
        [datacatalog.SearchCatalogRequest], Awaitable[datacatalog.SearchCatalogResponse]
    ]:
        r"""Return a callable for the search catalog method over gRPC.

        Searches Data Catalog for multiple resources like entries and
        tags that match a query.

        This is a [Custom Method]
        (https://cloud.google.com/apis/design/custom_methods) that
        doesn't return all information on a resource, only its ID and
        high level fields. To get more information, you can subsequently
        call specific get methods.

        Note: Data Catalog search queries don't guarantee full recall.
        Results that match your query might not be returned, even in
        subsequent result pages. Additionally, returned (and not
        returned) results can vary if you repeat search queries.

        For more information, see [Data Catalog search syntax]
        (https://cloud.google.com/data-catalog/docs/how-to/search-reference).

        Returns:
            Callable[[~.SearchCatalogRequest],
                    Awaitable[~.SearchCatalogResponse]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "search_catalog" not in self._stubs:
            self._stubs["search_catalog"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/SearchCatalog",
                request_serializer=datacatalog.SearchCatalogRequest.serialize,
                response_deserializer=datacatalog.SearchCatalogResponse.deserialize,
            )
        return self._stubs["search_catalog"]

    @property
    def create_entry_group(
        self,
    ) -> Callable[
        [datacatalog.CreateEntryGroupRequest], Awaitable[datacatalog.EntryGroup]
    ]:
        r"""Return a callable for the create entry group method over gRPC.

        Creates an entry group.

        An entry group contains logically related entries together with
        `Cloud Identity and Access
        Management </data-catalog/docs/concepts/iam>`__ policies. These
        policies specify users who can create, edit, and view entries
        within entry groups.

        Data Catalog automatically creates entry groups with names that
        start with the ``@`` symbol for the following resources:

        -  BigQuery entries (``@bigquery``)
        -  Pub/Sub topics (``@pubsub``)
        -  Dataproc Metastore services
           (``@dataproc_metastore_{SERVICE_NAME_HASH}``)

        You can create your own entry groups for Cloud Storage fileset
        entries and custom entries together with the corresponding IAM
        policies. User-created entry groups can't contain the ``@``
        symbol, it is reserved for automatically created groups.

        Entry groups, like entries, can be searched.

        A maximum of 10,000 entry groups may be created per organization
        across all locations.

        You must enable the Data Catalog API in the project identified
        by the ``parent`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.CreateEntryGroupRequest],
                    Awaitable[~.EntryGroup]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "create_entry_group" not in self._stubs:
            self._stubs["create_entry_group"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/CreateEntryGroup",
                request_serializer=datacatalog.CreateEntryGroupRequest.serialize,
                response_deserializer=datacatalog.EntryGroup.deserialize,
            )
        return self._stubs["create_entry_group"]

    @property
    def get_entry_group(
        self,
    ) -> Callable[
        [datacatalog.GetEntryGroupRequest], Awaitable[datacatalog.EntryGroup]
    ]:
        r"""Return a callable for the get entry group method over gRPC.

        Gets an entry group.

        Returns:
            Callable[[~.GetEntryGroupRequest],
                    Awaitable[~.EntryGroup]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "get_entry_group" not in self._stubs:
            self._stubs["get_entry_group"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/GetEntryGroup",
                request_serializer=datacatalog.GetEntryGroupRequest.serialize,
                response_deserializer=datacatalog.EntryGroup.deserialize,
            )
        return self._stubs["get_entry_group"]

    @property
    def update_entry_group(
        self,
    ) -> Callable[
        [datacatalog.UpdateEntryGroupRequest], Awaitable[datacatalog.EntryGroup]
    ]:
        r"""Return a callable for the update entry group method over gRPC.

        Updates an entry group.

        You must enable the Data Catalog API in the project identified
        by the ``entry_group.name`` parameter. For more information, see
        `Data Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.UpdateEntryGroupRequest],
                    Awaitable[~.EntryGroup]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "update_entry_group" not in self._stubs:
            self._stubs["update_entry_group"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/UpdateEntryGroup",
                request_serializer=datacatalog.UpdateEntryGroupRequest.serialize,
                response_deserializer=datacatalog.EntryGroup.deserialize,
            )
        return self._stubs["update_entry_group"]

    @property
    def delete_entry_group(
        self,
    ) -> Callable[[datacatalog.DeleteEntryGroupRequest], Awaitable[empty_pb2.Empty]]:
        r"""Return a callable for the delete entry group method over gRPC.

        Deletes an entry group.

        You must enable the Data Catalog API in the project identified
        by the ``name`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.DeleteEntryGroupRequest],
                    Awaitable[~.Empty]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "delete_entry_group" not in self._stubs:
            self._stubs["delete_entry_group"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/DeleteEntryGroup",
                request_serializer=datacatalog.DeleteEntryGroupRequest.serialize,
                response_deserializer=empty_pb2.Empty.FromString,
            )
        return self._stubs["delete_entry_group"]

    @property
    def list_entry_groups(
        self,
    ) -> Callable[
        [datacatalog.ListEntryGroupsRequest],
        Awaitable[datacatalog.ListEntryGroupsResponse],
    ]:
        r"""Return a callable for the list entry groups method over gRPC.

        Lists entry groups.

        Returns:
            Callable[[~.ListEntryGroupsRequest],
                    Awaitable[~.ListEntryGroupsResponse]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "list_entry_groups" not in self._stubs:
            self._stubs["list_entry_groups"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/ListEntryGroups",
                request_serializer=datacatalog.ListEntryGroupsRequest.serialize,
                response_deserializer=datacatalog.ListEntryGroupsResponse.deserialize,
            )
        return self._stubs["list_entry_groups"]

    @property
    def create_entry(
        self,
    ) -> Callable[[datacatalog.CreateEntryRequest], Awaitable[datacatalog.Entry]]:
        r"""Return a callable for the create entry method over gRPC.

        Creates an entry.

        You can create entries only with 'FILESET', 'CLUSTER',
        'DATA_STREAM', or custom types. Data Catalog automatically
        creates entries with other types during metadata ingestion from
        integrated systems.

        You must enable the Data Catalog API in the project identified
        by the ``parent`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        An entry group can have a maximum of 100,000 entries.

        Returns:
            Callable[[~.CreateEntryRequest],
                    Awaitable[~.Entry]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "create_entry" not in self._stubs:
            self._stubs["create_entry"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/CreateEntry",
                request_serializer=datacatalog.CreateEntryRequest.serialize,
                response_deserializer=datacatalog.Entry.deserialize,
            )
        return self._stubs["create_entry"]

    @property
    def update_entry(
        self,
    ) -> Callable[[datacatalog.UpdateEntryRequest], Awaitable[datacatalog.Entry]]:
        r"""Return a callable for the update entry method over gRPC.

        Updates an existing entry.

        You must enable the Data Catalog API in the project identified
        by the ``entry.name`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.UpdateEntryRequest],
                    Awaitable[~.Entry]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "update_entry" not in self._stubs:
            self._stubs["update_entry"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/UpdateEntry",
                request_serializer=datacatalog.UpdateEntryRequest.serialize,
                response_deserializer=datacatalog.Entry.deserialize,
            )
        return self._stubs["update_entry"]

    @property
    def delete_entry(
        self,
    ) -> Callable[[datacatalog.DeleteEntryRequest], Awaitable[empty_pb2.Empty]]:
        r"""Return a callable for the delete entry method over gRPC.

        Deletes an existing entry.

        You can delete only the entries created by the
        [CreateEntry][google.cloud.datacatalog.v1.DataCatalog.CreateEntry]
        method.

        You must enable the Data Catalog API in the project identified
        by the ``name`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.DeleteEntryRequest],
                    Awaitable[~.Empty]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "delete_entry" not in self._stubs:
            self._stubs["delete_entry"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/DeleteEntry",
                request_serializer=datacatalog.DeleteEntryRequest.serialize,
                response_deserializer=empty_pb2.Empty.FromString,
            )
        return self._stubs["delete_entry"]

    @property
    def get_entry(
        self,
    ) -> Callable[[datacatalog.GetEntryRequest], Awaitable[datacatalog.Entry]]:
        r"""Return a callable for the get entry method over gRPC.

        Gets an entry.

        Returns:
            Callable[[~.GetEntryRequest],
                    Awaitable[~.Entry]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "get_entry" not in self._stubs:
            self._stubs["get_entry"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/GetEntry",
                request_serializer=datacatalog.GetEntryRequest.serialize,
                response_deserializer=datacatalog.Entry.deserialize,
            )
        return self._stubs["get_entry"]

    @property
    def lookup_entry(
        self,
    ) -> Callable[[datacatalog.LookupEntryRequest], Awaitable[datacatalog.Entry]]:
        r"""Return a callable for the lookup entry method over gRPC.

        Gets an entry by its target resource name.
        The resource name comes from the source Google Cloud
        Platform service.

        Returns:
            Callable[[~.LookupEntryRequest],
                    Awaitable[~.Entry]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "lookup_entry" not in self._stubs:
            self._stubs["lookup_entry"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/LookupEntry",
                request_serializer=datacatalog.LookupEntryRequest.serialize,
                response_deserializer=datacatalog.Entry.deserialize,
            )
        return self._stubs["lookup_entry"]

    @property
    def list_entries(
        self,
    ) -> Callable[
        [datacatalog.ListEntriesRequest], Awaitable[datacatalog.ListEntriesResponse]
    ]:
        r"""Return a callable for the list entries method over gRPC.

        Lists entries.

        Note: Currently, this method can list only custom entries. To
        get a list of both custom and automatically created entries, use
        [SearchCatalog][google.cloud.datacatalog.v1.DataCatalog.SearchCatalog].

        Returns:
            Callable[[~.ListEntriesRequest],
                    Awaitable[~.ListEntriesResponse]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "list_entries" not in self._stubs:
            self._stubs["list_entries"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/ListEntries",
                request_serializer=datacatalog.ListEntriesRequest.serialize,
                response_deserializer=datacatalog.ListEntriesResponse.deserialize,
            )
        return self._stubs["list_entries"]

    @property
    def modify_entry_overview(
        self,
    ) -> Callable[
        [datacatalog.ModifyEntryOverviewRequest], Awaitable[datacatalog.EntryOverview]
    ]:
        r"""Return a callable for the modify entry overview method over gRPC.

        Modifies entry overview, part of the business context of an
        [Entry][google.cloud.datacatalog.v1.Entry].

        To call this method, you must have the
        ``datacatalog.entries.updateOverview`` IAM permission on the
        corresponding project.

        Returns:
            Callable[[~.ModifyEntryOverviewRequest],
                    Awaitable[~.EntryOverview]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "modify_entry_overview" not in self._stubs:
            self._stubs["modify_entry_overview"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/ModifyEntryOverview",
                request_serializer=datacatalog.ModifyEntryOverviewRequest.serialize,
                response_deserializer=datacatalog.EntryOverview.deserialize,
            )
        return self._stubs["modify_entry_overview"]

    @property
    def modify_entry_contacts(
        self,
    ) -> Callable[
        [datacatalog.ModifyEntryContactsRequest], Awaitable[datacatalog.Contacts]
    ]:
        r"""Return a callable for the modify entry contacts method over gRPC.

        Modifies contacts, part of the business context of an
        [Entry][google.cloud.datacatalog.v1.Entry].

        To call this method, you must have the
        ``datacatalog.entries.updateContacts`` IAM permission on the
        corresponding project.

        Returns:
            Callable[[~.ModifyEntryContactsRequest],
                    Awaitable[~.Contacts]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "modify_entry_contacts" not in self._stubs:
            self._stubs["modify_entry_contacts"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/ModifyEntryContacts",
                request_serializer=datacatalog.ModifyEntryContactsRequest.serialize,
                response_deserializer=datacatalog.Contacts.deserialize,
            )
        return self._stubs["modify_entry_contacts"]

    @property
    def create_tag_template(
        self,
    ) -> Callable[[datacatalog.CreateTagTemplateRequest], Awaitable[tags.TagTemplate]]:
        r"""Return a callable for the create tag template method over gRPC.

        Creates a tag template.

        You must enable the Data Catalog API in the project identified
        by the ``parent`` parameter. For more information, see [Data
        Catalog resource project]
        (https://cloud.google.com/data-catalog/docs/concepts/resource-project).

        Returns:
            Callable[[~.CreateTagTemplateRequest],
                    Awaitable[~.TagTemplate]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "create_tag_template" not in self._stubs:
            self._stubs["create_tag_template"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/CreateTagTemplate",
                request_serializer=datacatalog.CreateTagTemplateRequest.serialize,
                response_deserializer=tags.TagTemplate.deserialize,
            )
        return self._stubs["create_tag_template"]

    @property
    def get_tag_template(
        self,
    ) -> Callable[[datacatalog.GetTagTemplateRequest], Awaitable[tags.TagTemplate]]:
        r"""Return a callable for the get tag template method over gRPC.

        Gets a tag template.

        Returns:
            Callable[[~.GetTagTemplateRequest],
                    Awaitable[~.TagTemplate]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "get_tag_template" not in self._stubs:
            self._stubs["get_tag_template"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/GetTagTemplate",
                request_serializer=datacatalog.GetTagTemplateRequest.serialize,
                response_deserializer=tags.TagTemplate.deserialize,
            )
        return self._stubs["get_tag_template"]

    @property
    def update_tag_template(
        self,
    ) -> Callable[[datacatalog.UpdateTagTemplateRequest], Awaitable[tags.TagTemplate]]:
        r"""Return a callable for the update tag template method over gRPC.

        Updates a tag template.

        You can't update template fields with this method. These fields
        are separate resources with their own create, update, and delete
        methods.

        You must enable the Data Catalog API in the project identified
        by the ``tag_template.name`` parameter. For more information,
        see `Data Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.UpdateTagTemplateRequest],
                    Awaitable[~.TagTemplate]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "update_tag_template" not in self._stubs:
            self._stubs["update_tag_template"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/UpdateTagTemplate",
                request_serializer=datacatalog.UpdateTagTemplateRequest.serialize,
                response_deserializer=tags.TagTemplate.deserialize,
            )
        return self._stubs["update_tag_template"]

    @property
    def delete_tag_template(
        self,
    ) -> Callable[[datacatalog.DeleteTagTemplateRequest], Awaitable[empty_pb2.Empty]]:
        r"""Return a callable for the delete tag template method over gRPC.

        Deletes a tag template and all tags that use it.

        You must enable the Data Catalog API in the project identified
        by the ``name`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.DeleteTagTemplateRequest],
                    Awaitable[~.Empty]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "delete_tag_template" not in self._stubs:
            self._stubs["delete_tag_template"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/DeleteTagTemplate",
                request_serializer=datacatalog.DeleteTagTemplateRequest.serialize,
                response_deserializer=empty_pb2.Empty.FromString,
            )
        return self._stubs["delete_tag_template"]

    @property
    def create_tag_template_field(
        self,
    ) -> Callable[
        [datacatalog.CreateTagTemplateFieldRequest], Awaitable[tags.TagTemplateField]
    ]:
        r"""Return a callable for the create tag template field method over gRPC.

        Creates a field in a tag template.

        You must enable the Data Catalog API in the project identified
        by the ``parent`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.CreateTagTemplateFieldRequest],
                    Awaitable[~.TagTemplateField]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "create_tag_template_field" not in self._stubs:
            self._stubs["create_tag_template_field"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/CreateTagTemplateField",
                request_serializer=datacatalog.CreateTagTemplateFieldRequest.serialize,
                response_deserializer=tags.TagTemplateField.deserialize,
            )
        return self._stubs["create_tag_template_field"]

    @property
    def update_tag_template_field(
        self,
    ) -> Callable[
        [datacatalog.UpdateTagTemplateFieldRequest], Awaitable[tags.TagTemplateField]
    ]:
        r"""Return a callable for the update tag template field method over gRPC.

        Updates a field in a tag template.

        You can't update the field type with this method.

        You must enable the Data Catalog API in the project identified
        by the ``name`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.UpdateTagTemplateFieldRequest],
                    Awaitable[~.TagTemplateField]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "update_tag_template_field" not in self._stubs:
            self._stubs["update_tag_template_field"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/UpdateTagTemplateField",
                request_serializer=datacatalog.UpdateTagTemplateFieldRequest.serialize,
                response_deserializer=tags.TagTemplateField.deserialize,
            )
        return self._stubs["update_tag_template_field"]

    @property
    def rename_tag_template_field(
        self,
    ) -> Callable[
        [datacatalog.RenameTagTemplateFieldRequest], Awaitable[tags.TagTemplateField]
    ]:
        r"""Return a callable for the rename tag template field method over gRPC.

        Renames a field in a tag template.

        You must enable the Data Catalog API in the project identified
        by the ``name`` parameter. For more information, see [Data
        Catalog resource project]
        (https://cloud.google.com/data-catalog/docs/concepts/resource-project).

        Returns:
            Callable[[~.RenameTagTemplateFieldRequest],
                    Awaitable[~.TagTemplateField]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "rename_tag_template_field" not in self._stubs:
            self._stubs["rename_tag_template_field"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/RenameTagTemplateField",
                request_serializer=datacatalog.RenameTagTemplateFieldRequest.serialize,
                response_deserializer=tags.TagTemplateField.deserialize,
            )
        return self._stubs["rename_tag_template_field"]

    @property
    def rename_tag_template_field_enum_value(
        self,
    ) -> Callable[
        [datacatalog.RenameTagTemplateFieldEnumValueRequest],
        Awaitable[tags.TagTemplateField],
    ]:
        r"""Return a callable for the rename tag template field enum
        value method over gRPC.

        Renames an enum value in a tag template.
        Within a single enum field, enum values must be unique.

        Returns:
            Callable[[~.RenameTagTemplateFieldEnumValueRequest],
                    Awaitable[~.TagTemplateField]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "rename_tag_template_field_enum_value" not in self._stubs:
            self._stubs[
                "rename_tag_template_field_enum_value"
            ] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/RenameTagTemplateFieldEnumValue",
                request_serializer=datacatalog.RenameTagTemplateFieldEnumValueRequest.serialize,
                response_deserializer=tags.TagTemplateField.deserialize,
            )
        return self._stubs["rename_tag_template_field_enum_value"]

    @property
    def delete_tag_template_field(
        self,
    ) -> Callable[
        [datacatalog.DeleteTagTemplateFieldRequest], Awaitable[empty_pb2.Empty]
    ]:
        r"""Return a callable for the delete tag template field method over gRPC.

        Deletes a field in a tag template and all uses of this field
        from the tags based on this template.

        You must enable the Data Catalog API in the project identified
        by the ``name`` parameter. For more information, see `Data
        Catalog resource
        project <https://cloud.google.com/data-catalog/docs/concepts/resource-project>`__.

        Returns:
            Callable[[~.DeleteTagTemplateFieldRequest],
                    Awaitable[~.Empty]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "delete_tag_template_field" not in self._stubs:
            self._stubs["delete_tag_template_field"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/DeleteTagTemplateField",
                request_serializer=datacatalog.DeleteTagTemplateFieldRequest.serialize,
                response_deserializer=empty_pb2.Empty.FromString,
            )
        return self._stubs["delete_tag_template_field"]

    @property
    def create_tag(
        self,
    ) -> Callable[[datacatalog.CreateTagRequest], Awaitable[tags.Tag]]:
        r"""Return a callable for the create tag method over gRPC.

        Creates a tag and assigns it to:

        -  An [Entry][google.cloud.datacatalog.v1.Entry] if the method
           name is
           ``projects.locations.entryGroups.entries.tags.create``.
        -  Or [EntryGroup][google.cloud.datacatalog.v1.EntryGroup]if the
           method name is
           ``projects.locations.entryGroups.tags.create``.

        Note: The project identified by the ``parent`` parameter for the
        [tag]
        (https://cloud.google.com/data-catalog/docs/reference/rest/v1/projects.locations.entryGroups.entries.tags/create#path-parameters)
        and the [tag template]
        (https://cloud.google.com/data-catalog/docs/reference/rest/v1/projects.locations.tagTemplates/create#path-parameters)
        used to create the tag must be in the same organization.

        Returns:
            Callable[[~.CreateTagRequest],
                    Awaitable[~.Tag]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "create_tag" not in self._stubs:
            self._stubs["create_tag"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/CreateTag",
                request_serializer=datacatalog.CreateTagRequest.serialize,
                response_deserializer=tags.Tag.deserialize,
            )
        return self._stubs["create_tag"]

    @property
    def update_tag(
        self,
    ) -> Callable[[datacatalog.UpdateTagRequest], Awaitable[tags.Tag]]:
        r"""Return a callable for the update tag method over gRPC.

        Updates an existing tag.

        Returns:
            Callable[[~.UpdateTagRequest],
                    Awaitable[~.Tag]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "update_tag" not in self._stubs:
            self._stubs["update_tag"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/UpdateTag",
                request_serializer=datacatalog.UpdateTagRequest.serialize,
                response_deserializer=tags.Tag.deserialize,
            )
        return self._stubs["update_tag"]

    @property
    def delete_tag(
        self,
    ) -> Callable[[datacatalog.DeleteTagRequest], Awaitable[empty_pb2.Empty]]:
        r"""Return a callable for the delete tag method over gRPC.

        Deletes a tag.

        Returns:
            Callable[[~.DeleteTagRequest],
                    Awaitable[~.Empty]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "delete_tag" not in self._stubs:
            self._stubs["delete_tag"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/DeleteTag",
                request_serializer=datacatalog.DeleteTagRequest.serialize,
                response_deserializer=empty_pb2.Empty.FromString,
            )
        return self._stubs["delete_tag"]

    @property
    def list_tags(
        self,
    ) -> Callable[
        [datacatalog.ListTagsRequest], Awaitable[datacatalog.ListTagsResponse]
    ]:
        r"""Return a callable for the list tags method over gRPC.

        Lists tags assigned to an
        [Entry][google.cloud.datacatalog.v1.Entry]. The
        [columns][google.cloud.datacatalog.v1.Tag.column] in the
        response are lowercased.

        Returns:
            Callable[[~.ListTagsRequest],
                    Awaitable[~.ListTagsResponse]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "list_tags" not in self._stubs:
            self._stubs["list_tags"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/ListTags",
                request_serializer=datacatalog.ListTagsRequest.serialize,
                response_deserializer=datacatalog.ListTagsResponse.deserialize,
            )
        return self._stubs["list_tags"]

    @property
    def reconcile_tags(
        self,
    ) -> Callable[
        [datacatalog.ReconcileTagsRequest], Awaitable[operations_pb2.Operation]
    ]:
        r"""Return a callable for the reconcile tags method over gRPC.

        ``ReconcileTags`` creates or updates a list of tags on the
        entry. If the
        [ReconcileTagsRequest.force_delete_missing][google.cloud.datacatalog.v1.ReconcileTagsRequest.force_delete_missing]
        parameter is set, the operation deletes tags not included in the
        input tag list.

        ``ReconcileTags`` returns a [long-running operation]
        [google.longrunning.Operation] resource that can be queried with
        [Operations.GetOperation][google.longrunning.Operations.GetOperation]
        to return [ReconcileTagsMetadata]
        [google.cloud.datacatalog.v1.ReconcileTagsMetadata] and a
        [ReconcileTagsResponse]
        [google.cloud.datacatalog.v1.ReconcileTagsResponse] message.

        Returns:
            Callable[[~.ReconcileTagsRequest],
                    Awaitable[~.Operation]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "reconcile_tags" not in self._stubs:
            self._stubs["reconcile_tags"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/ReconcileTags",
                request_serializer=datacatalog.ReconcileTagsRequest.serialize,
                response_deserializer=operations_pb2.Operation.FromString,
            )
        return self._stubs["reconcile_tags"]

    @property
    def star_entry(
        self,
    ) -> Callable[
        [datacatalog.StarEntryRequest], Awaitable[datacatalog.StarEntryResponse]
    ]:
        r"""Return a callable for the star entry method over gRPC.

        Marks an [Entry][google.cloud.datacatalog.v1.Entry] as starred
        by the current user. Starring information is private to each
        user.

        Returns:
            Callable[[~.StarEntryRequest],
                    Awaitable[~.StarEntryResponse]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "star_entry" not in self._stubs:
            self._stubs["star_entry"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/StarEntry",
                request_serializer=datacatalog.StarEntryRequest.serialize,
                response_deserializer=datacatalog.StarEntryResponse.deserialize,
            )
        return self._stubs["star_entry"]

    @property
    def unstar_entry(
        self,
    ) -> Callable[
        [datacatalog.UnstarEntryRequest], Awaitable[datacatalog.UnstarEntryResponse]
    ]:
        r"""Return a callable for the unstar entry method over gRPC.

        Marks an [Entry][google.cloud.datacatalog.v1.Entry] as NOT
        starred by the current user. Starring information is private to
        each user.

        Returns:
            Callable[[~.UnstarEntryRequest],
                    Awaitable[~.UnstarEntryResponse]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "unstar_entry" not in self._stubs:
            self._stubs["unstar_entry"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/UnstarEntry",
                request_serializer=datacatalog.UnstarEntryRequest.serialize,
                response_deserializer=datacatalog.UnstarEntryResponse.deserialize,
            )
        return self._stubs["unstar_entry"]

    @property
    def set_iam_policy(
        self,
    ) -> Callable[[iam_policy_pb2.SetIamPolicyRequest], Awaitable[policy_pb2.Policy]]:
        r"""Return a callable for the set iam policy method over gRPC.

        Sets an access control policy for a resource. Replaces any
        existing policy.

        Supported resources are:

        -  Tag templates
        -  Entry groups

        Note: This method sets policies only within Data Catalog and
        can't be used to manage policies in BigQuery, Pub/Sub, Dataproc
        Metastore, and any external Google Cloud Platform resources
        synced with the Data Catalog.

        To call this method, you must have the following Google IAM
        permissions:

        -  ``datacatalog.tagTemplates.setIamPolicy`` to set policies on
           tag templates.
        -  ``datacatalog.entryGroups.setIamPolicy`` to set policies on
           entry groups.

        Returns:
            Callable[[~.SetIamPolicyRequest],
                    Awaitable[~.Policy]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "set_iam_policy" not in self._stubs:
            self._stubs["set_iam_policy"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/SetIamPolicy",
                request_serializer=iam_policy_pb2.SetIamPolicyRequest.SerializeToString,
                response_deserializer=policy_pb2.Policy.FromString,
            )
        return self._stubs["set_iam_policy"]

    @property
    def get_iam_policy(
        self,
    ) -> Callable[[iam_policy_pb2.GetIamPolicyRequest], Awaitable[policy_pb2.Policy]]:
        r"""Return a callable for the get iam policy method over gRPC.

        Gets the access control policy for a resource.

        May return:

        -  A\ ``NOT_FOUND`` error if the resource doesn't exist or you
           don't have the permission to view it.
        -  An empty policy if the resource exists but doesn't have a set
           policy.

        Supported resources are:

        -  Tag templates
        -  Entry groups

        Note: This method doesn't get policies from Google Cloud
        Platform resources ingested into Data Catalog.

        To call this method, you must have the following Google IAM
        permissions:

        -  ``datacatalog.tagTemplates.getIamPolicy`` to get policies on
           tag templates.
        -  ``datacatalog.entryGroups.getIamPolicy`` to get policies on
           entry groups.

        Returns:
            Callable[[~.GetIamPolicyRequest],
                    Awaitable[~.Policy]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "get_iam_policy" not in self._stubs:
            self._stubs["get_iam_policy"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/GetIamPolicy",
                request_serializer=iam_policy_pb2.GetIamPolicyRequest.SerializeToString,
                response_deserializer=policy_pb2.Policy.FromString,
            )
        return self._stubs["get_iam_policy"]

    @property
    def test_iam_permissions(
        self,
    ) -> Callable[
        [iam_policy_pb2.TestIamPermissionsRequest],
        Awaitable[iam_policy_pb2.TestIamPermissionsResponse],
    ]:
        r"""Return a callable for the test iam permissions method over gRPC.

        Gets your permissions on a resource.
        Returns an empty set of permissions if the resource
        doesn't exist.
        Supported resources are:

        - Tag templates
        - Entry groups

        Note: This method gets policies only within Data Catalog
        and can't be used to get policies from BigQuery,
        Pub/Sub, Dataproc Metastore, and any external Google
        Cloud Platform resources ingested into Data Catalog.
        No Google IAM permissions are required to call this
        method.

        Returns:
            Callable[[~.TestIamPermissionsRequest],
                    Awaitable[~.TestIamPermissionsResponse]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "test_iam_permissions" not in self._stubs:
            self._stubs["test_iam_permissions"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/TestIamPermissions",
                request_serializer=iam_policy_pb2.TestIamPermissionsRequest.SerializeToString,
                response_deserializer=iam_policy_pb2.TestIamPermissionsResponse.FromString,
            )
        return self._stubs["test_iam_permissions"]

    @property
    def import_entries(
        self,
    ) -> Callable[
        [datacatalog.ImportEntriesRequest], Awaitable[operations_pb2.Operation]
    ]:
        r"""Return a callable for the import entries method over gRPC.

        Imports entries from a source, such as data previously dumped
        into a Cloud Storage bucket, into Data Catalog. Import of
        entries is a sync operation that reconciles the state of the
        third-party system with the Data Catalog.

        ``ImportEntries`` accepts source data snapshots of a third-party
        system. Snapshot should be delivered as a .wire or
        base65-encoded .txt file containing a sequence of Protocol
        Buffer messages of
        [DumpItem][google.cloud.datacatalog.v1.DumpItem] type.

        ``ImportEntries`` returns a [long-running operation]
        [google.longrunning.Operation] resource that can be queried with
        [Operations.GetOperation][google.longrunning.Operations.GetOperation]
        to return
        [ImportEntriesMetadata][google.cloud.datacatalog.v1.ImportEntriesMetadata]
        and an
        [ImportEntriesResponse][google.cloud.datacatalog.v1.ImportEntriesResponse]
        message.

        Returns:
            Callable[[~.ImportEntriesRequest],
                    Awaitable[~.Operation]]:
                A function that, when called, will call the underlying RPC
                on the server.
        """
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "import_entries" not in self._stubs:
            self._stubs["import_entries"] = self.grpc_channel.unary_unary(
                "/google.cloud.datacatalog.v1.DataCatalog/ImportEntries",
                request_serializer=datacatalog.ImportEntriesRequest.serialize,
                response_deserializer=operations_pb2.Operation.FromString,
            )
        return self._stubs["import_entries"]

    def close(self):
        return self.grpc_channel.close()

    @property
    def delete_operation(
        self,
    ) -> Callable[[operations_pb2.DeleteOperationRequest], None]:
        r"""Return a callable for the delete_operation method over gRPC."""
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "delete_operation" not in self._stubs:
            self._stubs["delete_operation"] = self.grpc_channel.unary_unary(
                "/google.longrunning.Operations/DeleteOperation",
                request_serializer=operations_pb2.DeleteOperationRequest.SerializeToString,
                response_deserializer=None,
            )
        return self._stubs["delete_operation"]

    @property
    def cancel_operation(
        self,
    ) -> Callable[[operations_pb2.CancelOperationRequest], None]:
        r"""Return a callable for the cancel_operation method over gRPC."""
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "cancel_operation" not in self._stubs:
            self._stubs["cancel_operation"] = self.grpc_channel.unary_unary(
                "/google.longrunning.Operations/CancelOperation",
                request_serializer=operations_pb2.CancelOperationRequest.SerializeToString,
                response_deserializer=None,
            )
        return self._stubs["cancel_operation"]

    @property
    def get_operation(
        self,
    ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]:
        r"""Return a callable for the get_operation method over gRPC."""
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "get_operation" not in self._stubs:
            self._stubs["get_operation"] = self.grpc_channel.unary_unary(
                "/google.longrunning.Operations/GetOperation",
                request_serializer=operations_pb2.GetOperationRequest.SerializeToString,
                response_deserializer=operations_pb2.Operation.FromString,
            )
        return self._stubs["get_operation"]

    @property
    def list_operations(
        self,
    ) -> Callable[
        [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse
    ]:
        r"""Return a callable for the list_operations method over gRPC."""
        # Generate a "stub function" on-the-fly which will actually make
        # the request.
        # gRPC handles serialization and deserialization, so we just need
        # to pass in the functions for each.
        if "list_operations" not in self._stubs:
            self._stubs["list_operations"] = self.grpc_channel.unary_unary(
                "/google.longrunning.Operations/ListOperations",
                request_serializer=operations_pb2.ListOperationsRequest.SerializeToString,
                response_deserializer=operations_pb2.ListOperationsResponse.FromString,
            )
        return self._stubs["list_operations"]

__all__ = ("DataCatalogGrpcAsyncIOTransport",)


import argparse
import xml.etree.cElementTree as ET
import json
import itertools
from xml.dom import minidom

##def main():
##    prog = 'myTool'
##    description = ('A command line interface for visualizing'
##                   'format reading, writing.')
##    parser = argparse.ArgumentParser(prog = prog, description = description)
##    parser.add_argument('infile', nargs = '?', type = argparse.FileType(),
##                        help - 'a string to be formated')
##    parser.add_argument('format type', nargs = '?', type = argparse.
##    options = parser.parse_args()

class reader:
    def __init__(self, fileName):
        self.file = fileName

    def readLine(self):
        lines = self.file.readline()
        return lines

    def fileSplit(self):
        for lines in self.file:
            data = lines.split()
        return data

class visualizer:
    def __init__(self, dataEntry):
        self.data = dataEntry

    def displayXml(self):
        root = ET.Element("root")
        head = ET.SubElement(root, "data")
        name = ET.SubElement(head, self.data[0])
        name.text = self.data[1]
        phone = ET.SubElement(head, self.data[2])
        phone.text = self.data[3]
        address = ET.SubElement(head, self.data[4])
        address.text = self.data[5]
        tree = ET.ElementTree(root)
        initialString = ET.tostring(root, 'utf-8')
        printParsed = minidom.parseString(initialString)
        printParsed = printParsed.toprettyxml(indent = "\t")
        #writer = tree.write("data.xml") #for writing the xml file
        return printParsed

    def displayJson(self):
        d = dict(itertools.zip_longest(self.data[::2], self.data[1::2], fillvalue=''))
        printParsed = json.dumps(d, indent = 4)
        #with open('data.json', 'w') as outfile:
        #    json.dump(l,outfile, indent = 4)    #for writing the json file
        return printParsed

dataFile = reader(open('data.txt', 'r'))

splitFile = dataFile.fileSplit()

splitVal = visualizer(splitFile)

print(splitVal.displayXml())
print(splitVal.displayJson())


from django.utils.translation import ugettext_lazy as _

CATEGORIES = (
    ("M1", _("M1")),
    ("M2", _("M2")),
    ("N1", _("N1")),
    ("N2", _("N2")),
    ("L3e", _("L3e")),
    ("L4e", _("L4e")),
    ("L5e", _("L5e")),
    ("L6e", _("L6e")),
)

CONTRACT_TYPES = (
    ("FIXED_PERIOD", _("Fixed period")),
    ("OPEN_ENDED", _("Open ended")),
)

VEHICLE_TYPES = (
    ("BENSIN", _("Bensin")),
    ("DIESEL", _("Diesel")),
    ("BIFUEL", _("Bifuel")),
)


# Create a web address and store it in a variable
url = "https://google.com"

# Store the IP address within a string variable
ip = "192.168.1.1"

# Create some variables to store how many times the site was visited each day
monday = 1000
tuesday = 2000
wednesday = 3000
thursday = 1000
friday = 200
saturday = 900000
sunday = 900

# Add up all of the daily hits for the week and store them in a variable
daily_hits_total = monday + tuesday + wednesday + thursday + friday + saturday + sunday

# Find the average daily hits for the week
average_hits = daily_hits_total / 7

# Print out all the summaries to the screen
print ("url is: " + url)
print ("ip is: " + ip)
print ("average hits is: " + str(int(average_hits)))


#!/usr/bin/python3

import json
import time
import random
import requests

#https://pkgstore.datahub.io/JohnSnowLabs/country-and-continent-codes-list/country-and-continent-codes-list-csv_json/data/c218eebbf2f8545f3db9051ac893d69c/country-and-continent-codes-list-csv_json.json
filepath = "cc.json"
continent = "Europe"
countrycodes = []
ccasn = 'http://www.cc2asn.com/data/'
ccasnend = '_ipv4'

def writer(cc,string):
        ccstr = cc + '-ranges.txt'
        file = open(ccstr, "w+")
        file.write(string)
        file.close()
        print("wrote " +ccstr)

def iptoasn(cc):
        cleancc = cc.replace("\n","")
        cleanstr = ccasn + cleancc + ccasnend
        randwait = random.randrange(1,4)
        r = requests.get(cleanstr)
        print(r.text)
        writer(cleancc,r.text)
        time.sleep(randwait)

def ccgen():
	counter = 0
	with open(filepath,"r") as file:
		data = json.load(file)
		for x in data:
			if x['Continent_Name'] == continent:
				countrycodes.append(x['Two_Letter_Country_Code'] )
				counter += 1

#main starts here
ccgen()
for x in countrycodes:
	iptoasn(x.lower())
print(countrycodes)


# Sample Dataset: FASTA format of at most 10 DNA strings
# return a consensus string and profile matrix for the collection

def main():
    import numpy as np

    ini_list = []
    # type in textfile name, and opens text file
    textfile_name = input("input textfile name here: (have to be on same directoy as .py)")
    FASTA_string = open(f"{textfile_name}.txt", "r")

    # assign variable to iterable and iterate through lines
    lines = FASTA_string.readlines()
    lines.pop(0)
    gene_string = ""
    for line in lines:
        # removes all gene tags (which start with '>'), and adds collected gene_string
        if line[0] is ">":
            ini_list.append(gene_string)
            gene_string = ""
        # collects gene string as they can span multiple lines
        else:
            clean_line = line.rstrip("\n\r")
            gene_string += clean_line

        # edge case where the last DNA sequence is not counted due to appending when > is present next
        if line == lines[len(lines) - 1]:
            ini_list.append(gene_string)

    # ************ convert string into matrix! ************
    ini_matrix = []
    for DNA_sequence in ini_list:
        # list comprehension to put all nucleotide into matrix
        ini_matrix.append([nucleotide for nucleotide in DNA_sequence])

    matrix = np.array(ini_matrix).reshape(len(ini_matrix), len(ini_matrix[0]))

    # character lists to put later
    A = []
    C = []
    G = []
    T = []
    final_A_string = "A: "
    final_C_string = "C: "
    final_G_string = "G: "
    final_T_string = "T: "

    # len(ini_list[0]) is the length of the list, or how many columns there are in the matrix
    for column in range(len(ini_list[0])):
        # nucleotide counts, resets every column
        a = c = g = t = 0
        for nuc_character in matrix[:, column]:
            if nuc_character == "A":
                a += 1
            if nuc_character == "C":
                c += 1
            if nuc_character == "G":
                g += 1
            if nuc_character == "T":
                t += 1
        # after iterating through column of matrix, append counts to each respective list
        A.append(a), C.append(c), G.append(g), T.append(t)

    # now make consensus string
    def return_max_character(location, matrix1, matrix2, matrix3, matrix4):
        """
        recursive solution to finding which matrix has the greatest value, is this efficient? NO!,
        there are tons of different methods that are way quicker and better.
        I wanted to practice recursion and therefore I did it this way, since im not good at it
        NEEDS comparable data types.
        :param location: index of where the matrix will compare values
        :param matrix1: a matrix
        :param matrix2: another matrix
        :param matrix3: another matrix 2
        :param matrix4: another matrix 3
        :return: matrix with largest value when comparing at index
        """
        base = matrix1[location]
        if base < matrix2[location]:
            return return_max_character(location, matrix2, matrix2, matrix3, matrix4)
        if base < matrix3[location]:
            return return_max_character(location, matrix3, matrix2, matrix3, matrix4)
        if base < matrix4[location]:
            return return_max_character(location, matrix4, matrix2, matrix3, matrix4)
        else:
            return matrix1

    # iterates through all matrices, determines which has the greatest value at given index. appends string
    consensus_string = ""
    for index in range(len(A)):
        character = return_max_character(index, A, C, G, T)
        if character == A:
            consensus_string += "A"
        if character == C:
            consensus_string += "C"
        if character == G:
            consensus_string += "G"
        if character == T:
            consensus_string += "T"

    for number in range(len(A)):
        final_A_string += f"{A[number]} "
        final_C_string += f"{C[number]} "
        final_G_string += f"{G[number]} "
        final_T_string += f"{T[number]} "

    # final output
    print(consensus_string)
    print(f"{final_A_string} \n{final_C_string} \n{final_G_string} \n{final_T_string}")

if __name__ == "__main__":
    main()

Rosalind Bioinformatics/Consensus and Profile.py


import sys

import pygame

from bullet import Bullet
from alien import Alien
from time import sleep

from pygame.sprite import Group
from pygame import freetype
bunker1 = 0

alienCollidedWithBullets = False
numberOfTicks = 0
alien1 = 0;
bulletThatCollidedWithBunker = 0
bulletCollidedWithBunker = False
bullets1 = Group()
rowForBunkerPixel = 50
columnForBunkerPixel = 270
numberOfTimesIncremented = 0
numberOfTimesIncrementedForRow = 0
count = 0
count1 = 0

def check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets):
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:
            ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)
            break
def ship_hit(ai_settings,screen,stats,sb, ship, aliens, bullets):

  if stats.ships_left > 0:
    stats.ships_left -=1

    sb.prep_ships()

    aliens.empty()
    bullets.empty()

    create_fleet(ai_settings, screen,ship,aliens)
    ship.center_ship()

    sleep(0.5)
  else:
      stats.game_active = False
      pygame.mouse.set_visible(True)

def change_fleet_direction(ai_settings,aliens):
    for alien in aliens.sprites():
        alien.rect.y += ai_settings.fleet_drop_speed
    ai_settings.fleet_direction *= -1

def check_fleet_edges(ai_settings, aliens):
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai_settings, aliens)
            break

def update_aliens(ai_settings,screen,stats,sb,ship,aliens,bullets):
    check_fleet_edges(ai_settings,aliens)

    aliens.update()

    if pygame.sprite.spritecollideany(ship,aliens):
        ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)

    check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets)

    if pygame.sprite.spritecollideany(ship,aliens):
        print("Ship hit!!!!!")

def check_keydown_events(event,ai_settings,screen,ship,bullets,bunker):

    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True

    elif event.key == pygame.K_SPACE:

        fire_bullet(ai_settings, screen, ship, bullets,bunker)

    elif event.key == pygame.K_q:
        sys.exit()

def fire_bullet(ai_settings, screen, ship, bullets,bunker):

      if len(bullets) < ai_settings.bullets_allowed:

        new_bullet = Bullet(ai_settings,screen,ship,bunker)
        bullets.add(new_bullet)

def check_keyup_events(event,ship):
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False

    elif event.key == pygame.K_LEFT:
        ship.moving_left = False

def check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,bunker):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y)

        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event,ai_settings,screen,ship,bullets,bunker)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event,ship)

def check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y):
    if play_button.rect.collidepoint(mouse_x,mouse_y):

        button_clicked = play_button.rect.collidepoint(mouse_x,mouse_y)
    if button_clicked and not stats.game_active:
        ai_settings.initialize_dynamic_settings()
        pygame.mouse.set_visible(False)
        stats.reset_stats()
        stats.game_active = True

        sb.prep_score()
        sb.prep_high_score()
        sb.prep_level()
        sb.prep_ships()

        aliens.empty()
        bullets.empty()

        create_fleet(ai_settings,screen,ship,aliens)
        ship.center_ship()
def update_screen(ai_settings, screen,stats, sb,ship, aliens, bullets, play_button,bunker):

    screen.fill(ai_settings.bg_color)

    for bullet in bullets.sprites():
        bullet.draw_bullet()

    ship.blitme()

    bunkerCopy = bunker
    screen.blit(bunkerCopy,(50,270))
    del bunker

    aliens.draw(screen)

    sb.show_score()

    if not stats.game_active:
        play_button.draw_button()

    pygame.display.flip()

def update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets,bunkerGroup,bunker):
    global alienCollidedWithBullets
    bullets.update()
    for bullet in bullets.copy():
        if bullet.rect.bottom <=0:
            bullets.remove(bullet)

    check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets,bunkerGroup,bunker)

def check_high_score(stats,sb):

    if stats.score > stats.high_score:
        stats.high_score = stats.score
        sb.prep_high_score

def check_bullet_alien_collisions(ai_settings, screen,stats,sb, ship, aliens,bullets,bunkerGroup,bunker):

        pygame.draw.rect(screen,(0,0,255),bunker.get_rect(),5)
        pygame.display.update()

        global bunker12
        global count
        global count1

        gizo = True

        global bunkerRect

        global bulletThatCollidedWithBunker
        global bulletCollidedWithBunker
        global columnForBunkerPixel
        global rowForBunkerPixel
        global numberOfTimesIncremented
        global numberOfTimesIncrementedForRow

        rect5 = pygame.Rect((0,0),(500,500))

        temp = bunker

        bunker12 = bunker.copy()
        bunker12.scroll(50,270)

        print("bunker get parent")

        count1 = count1 + 1

        print("This is the location of the color pixel")

        print(bunker12.get_at((499,503)))

        try:

          if bulletCollidedWithBunker and numberOfTimesIncremented !=3:
              if(bunker12.get_at(((int)(bulletThatCollidedWithBunker.x-1), (int)(bulletThatCollidedWithBunker.y-1))) == (118,255,3)):
               bunker.set_at(((int)(bulletThatCollidedWithBunker.x - rowForBunkerPixel), (int)(bulletThatCollidedWithBunker.y - columnForBunkerPixel)), (255, 255, 255))
               columnForBunkerPixel = columnForBunkerPixel + 1
               numberOfTimesIncremented = numberOfTimesIncremented + 1
               print("column for bunker pixel")
               print(columnForBunkerPixel)

          if numberOfTimesIncremented == 3:
              numberOfTimesIncrementedForRow = numberOfTimesIncrementedForRow + 1
              columnForBunkerPixel = 270
              numberOfTimesIncremented = 0
              rowForBunkerPixel = rowForBunkerPixel + 1

          if numberOfTimesIncrementedForRow == 3:
              bulletCollidedWithBunker = False
              rowForBunkerPixel = 50
              columnForBunkerPixel = 270
              numberOfTimesIncrementedForRow = 0
              numberOfTimesIncremented = 0

          for bullet12 in bullets:

                print("bullet value")

                print((int)(bullet12.x), (int)(bullet12.y))
                print("color value")

                pygame.display.update()

                if(bunker12.get_at(((int)(bullet12.x), (int)(bullet12.y))) == (118,255,3) and bullet12.y >= 497  ):

                  bulletCollidedWithBunker = True

                  bulletThatCollidedWithBunker = bullet12

                  print("collided with the best bunker in the world")

                  bunker12 .set_at(((int)(bullet12.x-50), (int)(bullet12.y-270)),(255,255,255))

                  print("bunker's pixel color at location")

                  print("collided with bunker")

                  bullet12.kill()

        except IndexError:
            print("out of range")

        global alienCollidedWithBullets
        global numberOfTicks
        global alien1

        for alien in aliens:

           if(alien.collided_with(bullets)):
              alienCollidedWithBullets = True
              print("in here")
              alien1 = alien

        collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

        for aliens in collisions.values():
          stats.score += ai_settings.alien_points * len(aliens)
          sb.prep_score()
          check_high_score(stats, sb)

        if (alienCollidedWithBullets):
                part1OfCollision = pygame.image.load("images/enemy1Explosionp1.png")
                part2OfCollision = pygame.image.load("images/enemy1Explosionp2.png")
                part3OfCollision = pygame.image.load("images/enemy1Explosionp3.png")
                if numberOfTicks != 50:
                    screen.blit(part1OfCollision, alien1.rect)
                    pygame.display.update()

                if numberOfTicks >= 10 and numberOfTicks <= 20:
                    screen.blit(part2OfCollision, alien1.rect)
                    pygame.display.update()

                if numberOfTicks >= 20 and numberOfTicks <= 30:
                    screen.blit(part3OfCollision, alien1.rect)
                    pygame.display.update()

                if (numberOfTicks == 30):
                 numberOfTicks = 0
                 alienCollidedWithBullets = False

                else:
                 numberOfTicks = numberOfTicks + 1

        if len(aliens) == 0:
                 bullets.empty()
                 ai_settings.increase_speed()

                 stats.level += 1
                 sb.prep_level()
                 create_fleet(ai_settings,screen,ship,aliens)

def get_number_rows(ai_settings, ship_height, alien_height):
    available_space_y = (ai_settings.screen_height - (3 * alien_height) -ship_height)
    number_rows = int(available_space_y / ( 2 * alien_height))
    return number_rows

def get_number_aliens_x(ai_settings,alien_width):
        available_space_x = ai_settings.screen_width - 2 * alien_width
        number_aliens_x = int(available_space_x / (2 * alien_width))
        return number_aliens_x

def create_alien(ai_settings,screen,aliens,alien_number, row_number, image):
        alien = Alien(ai_settings, screen ,image)
        alien_width = alien.rect.width
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        aliens.add(alien)

def create_fleet(ai_settings,screen,ship,aliens):
    alien = Alien(ai_settings,screen, "images/blueAlien.bmp.png")
    number_aliens_x = get_number_aliens_x(ai_settings,alien.rect.width)
    number_rows = get_number_rows(ai_settings,ship.rect.height,alien.rect.height)

    for row_number in range(number_rows):
     for alien_number in range(number_aliens_x):
        if row_number == 0:
         create_alien(ai_settings,screen,aliens,alien_number, row_number,"images/blueAlien.bmp.png")

        if row_number == 1:

                create_alien(ai_settings, screen, aliens, alien_number, row_number, "images/greenAlien.png")

        if row_number == 2:
            create_alien(ai_settings, screen, aliens, alien_number, row_number, "images/pinkAlien.png")


import os
import json
import time

class Config():
	def __init__(self):
		self.json_config = {}
		try:
			with open('/usr/share/APP/instance/config_cerimonia.txt') as json_file:
				self.json_config = json.load(json_file)
		except:
			self.cria_config()

	def cria_config(self):
		self.json_config={}
		# ~ self.json_config = {'CONFIG':{}}
		self.json_config={
		'CONFIG':{
			"TIME":time.time(),
			"TIME_BLOCK_SENHA":60*5, # 5 MINUTOS
			"UPDATE":False,
			"IN_SERVER_IP":None,
			"LOCAL_IP":None,
			"VIDEO_FILES":[ "*.mp4", "*.mkv", "*.avi"],
			"AUDIO_FILES":["*.mp3", "*.wav"],
			"TOPICO_INT_IHM": "capela/ihm",
			"TOPICO_EXT_IHM": "capela/krause/ihm",
			"PORTA_MQTT": 1883,
			'VIDEO_IHM':False,
			'AUDIO_IHM':False,
			'CEMITERIO':'krause',
			'TOPICO_IN_SERVER':'capela/cerimonia',
			'TOPICO_EXT_SERVER':'capela/krause/cerimonia',
			'VIDEO_EXT':{
				'INIC_CH_PETALAS':218,
				'ACENDE_CENARIO':365,
				'INIC_PULSA_CRUZ':340,
				'INIC_SEQUENCIA':213,
				'INIC_FUMACA':208,
				'URL':'/usr/share/APP/videos/video_1.mp4'},
			'VIDEO_1':{
				'INIC_CH_PETALAS':218,
				'ACENDE_CENARIO':365,
				'INIC_PULSA_CRUZ':340,
				'INIC_SEQUENCIA':213,
				'INIC_FUMACA':208,
				'URL':'/usr/share/APP/videos/video_1.mp4'},
			'IHM_AUDIO':{
				'INDEX':None,
				'NAME':None,
				'VOLUME':50}}}

		with open('/usr/share/APP/instance/config_cerimonia.txt', 'w') as outfile:
			# ~ print(json.dumps(self.json_config, indent=2))
			json.dump(self.json_config, outfile)

	def reset_cenario(self):
		config = {}
		try:
			if sys.platform == 'win32':
				os.system("del /usr/share/APP/instance/config_cerimonia.txt")
			else:
				os.system('rm /usr/share/APP/instance/config_cerimonia.txt')
		except:
			pass

		self.cria_config()
		with open('/usr/share/APP/instance/config_cerimonia.txt') as json_file:
			config = json.load(json_file)
		return config

	def salva_config(self, data):
		with open('/usr/share/APP/instance/config_cerimonia.txt', 'w') as outfile:
			outfile.write(json.dumps(data , indent=4))


# @file path_utilities.py
# Code to help convert Edk2, absolute, and relative file paths
#
# Copyright (c) Microsoft Corporation
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
import os
import logging
import fnmatch
import glob
from typing import Iterable
from pathlib import Path

#
# Class to help convert from absolute path to EDK2 build path
# using workspace and packagepath variables
#

class Edk2Path(object):

    def __init__(self, ws: os.PathLike, packagepathlist: Iterable[os.PathLike], error_on_invalid_pp: bool = True):
        """ An Edk2Path object is an object that can be used to resolve edk2 relative paths

        Args:
            ws: absolute path or cwd relative path of the workspace.
            packagespathlist: list of packages path.
                Entries can be Absolute path, workspace relative path, or CWD relative.
            error_on_invalid_pp: default value is True. If packages path value is invalid raise exception
        """

        self.WorkspacePath = ws
        self.logger = logging.getLogger("Edk2Path")
        if (not os.path.isabs(ws)):
            self.WorkspacePath = os.path.abspath(os.path.join(os.getcwd(), ws))

        if (not os.path.isdir(self.WorkspacePath)):
            self.logger.error("Workspace path invalid.  {0}".format(ws))
            raise Exception("Workspace path invalid.  {0}".format(ws))

        # Set PackagePath
        self.PackagePathList = list()
        for a in packagepathlist:
            if (os.path.isabs(a)):
                self.PackagePathList.append(a)
            else:
                # see if workspace relative
                wsr = os.path.join(ws, a)
                if (os.path.isdir(wsr)):
                    self.PackagePathList.append(wsr)
                else:
                    # assume current working dir relative.  Will catch invalid dir when checking whole list
                    self.PackagePathList.append(os.path.abspath(os.path.join(os.getcwd(), a)))

        error = False
        for a in self.PackagePathList[:]:
            if (not os.path.isdir(a)):
                self.logger.log(logging.ERROR if error_on_invalid_pp else logging.WARNING,
                                "Invalid package path entry {0}".format(a))
                self.PackagePathList.remove(a)  # remove invalid path
                error = True

        # report error
        if (error and error_on_invalid_pp):
            raise Exception("Invalid package path directory(s)")

        # for each package path, trace from packagepath to the
        # either the workspace root or filesystem root and verify
        # no *.DEC file exists. This would signify a nested package.
        for package_path in self.PackagePathList:
            p = Path(package_path)
            ws = self.WorkspacePath
            while p != p.parent:
                if str(p).lower() == str(ws).lower():
                    break
                if len(glob.glob(f'{p}/*dec')) != 0:
                    raise Exception(f'Nested packages not allowed. Pkg path [{package_path}] nested in Package [{p}]')
                p = p.parent

    def GetEdk2RelativePathFromAbsolutePath(self, abspath):
        ''' Given an absolute path return a edk2 path relative to workspace or packagespath.

        Note: absolute path must be in the OS specific path form
        Note: the relative path will be in POSIX-like path form

        @param abspath: absolute path to a file or directory. Path must contain OS specific separator.

        @ret POSIX-like relative path to workspace or packagespath
        @ret None if path is not valid
        '''
        if abspath is None:
            return None

        relpath = None
        found = False

        # Check if the Absolute path starts with any of the package paths. If a match is found, build the relative
        # path based off that package.
        #
        # Sort the package paths from from longest to shortest. This handles the case where a package and a package
        # path are in the same directory. See the following path_utilities_test for a detailed explanation of the
        # scenario: test_get_relative_path_when_folder_is_next_to_package
        for packagepath in sorted((os.path.normcase(p) for p in self.PackagePathList), reverse=True):

            # If a match is found, use the original string to avoid change in case
            if os.path.normcase(abspath).startswith(packagepath):
                self.logger.debug("Successfully converted AbsPath to Edk2Relative Path using PackagePath")
                relpath = abspath[len(packagepath):]
                found = True
                break

        # If a match was not found, check if absolute path is based on the workspace root.
        if not found and os.path.normcase(abspath).startswith(os.path.normcase(self.WorkspacePath)):
            self.logger.debug("Successfully converted AbsPath to Edk2Relative Path using WorkspacePath")
            relpath = abspath[len(self.WorkspacePath):]
            found = True

        if found:
            relpath = relpath.replace(os.sep, "/").strip("/")
            self.logger.debug(f'[{abspath}] -> [{relpath}]')
            return relpath

        # Absolute path was not in reference to a package path or the workspace root.
        self.logger.error("Failed to convert AbsPath to Edk2Relative Path")
        self.logger.error(f'AbsolutePath: {abspath}')
        return None

    def GetAbsolutePathOnThisSystemFromEdk2RelativePath(self, relpath, log_errors=True):
        ''' Given a edk2 relative path return an absolute path to the file in this workspace.

        Note: The relative path must be in POSIX-like path form
        Note: The absolute path will be returned as an OS specific path form
        Note: For case insensitive operating systems the case of the input
        relpath will be used for the return value even if it doesn't match
        the case in the filesystem.

        If not valid or doesn't exist return None'''

        if relpath is None:
            return None
        relpath = relpath.replace("/", os.sep)
        abspath = os.path.join(self.WorkspacePath, relpath)
        if os.path.exists(abspath):
            return abspath

        for a in self.PackagePathList:
            abspath = os.path.join(a, relpath)
            if (os.path.exists(abspath)):
                return abspath
        if log_errors:
            self.logger.error("Failed to convert Edk2Relative Path to an Absolute Path on this system.")
            self.logger.error("Relative Path: %s" % relpath)

        return None

    def GetContainingPackage(self, InputPath):
        ''' Find the package this path belongs to using some Heuristic.  This isn't
        perfect but at least identifies the directory consistently.

        Note: The inputPath must be in the OS specific path form

        @param InputPath:  absolute path to a file, directory, or module. Supports both Windows and Linux like paths

        @ret Name of Package that the module is in.
        '''
        self.logger.debug("GetContainingPackage: %s" % InputPath)
        # Make a list that has the path case normalized for comparison.
        # This only does anything on Windows
        NormCasePackagesPathList = [os.path.normcase(x) for x in self.PackagePathList]

        # check InputPath to make sure it is at least in the folder structure of the code tree
        if os.path.normcase(self.WorkspacePath) not in os.path.normcase(InputPath):
            # not in workspace - check all the packages paths
            found_in_pp = False
            for p in NormCasePackagesPathList:
                if p in os.path.normcase(InputPath):
                    found_in_pp = True
                    break
            if (not found_in_pp):
                self.logger.error(f"{InputPath} not in code tree")
                self.logger.info("PackagePath is: %s" % os.pathsep.join(self.PackagePathList))
                self.logger.info("Workspace path is : %s" % self.WorkspacePath)
                return None

        # Start the search within the first available directory. If provided InputPath is a directory, start there,
        # else (if InputPath is a file) move to it's parent directory and start there.
        if os.path.isdir(InputPath):
            dirpathprevious = str(InputPath)
            dirpath = str(InputPath)
        else:
            dirpathprevious = os.path.dirname(InputPath)
            dirpath = os.path.dirname(InputPath)

        # InputPath is in workspace or PackagesPath for worst case scenario.
        for _ in range(100):  # 100 is just a counter to avoid infinite loops.  Path nodes are unlikely to exceed 100
            #
            # Check for a DEC file in this folder
            # if here then return the directory name as the "package"
            #
            for f in os.listdir(dirpath):
                if fnmatch.fnmatch(f.lower(), '*.dec'):
                    a = os.path.basename(dirpath)
                    self.logger.debug("Found DEC file at %s.  Pkg is: %s", dirpath, a)
                    return a

            #
            # if at the root of the workspace return the previous dir.
            # this catches cases where a package has no DEC
            #
            if os.path.normcase(dirpath) == os.path.normcase(self.WorkspacePath):
                a = os.path.basename(dirpathprevious)
                self.logger.debug("Reached Workspace Path.  Using previous directory: %s" % a)
                return a

            #
            # if at the root of a packagepath return the previous dir.
            # this catches cases where a package has no DEC
            #
            if os.path.normcase(dirpath) in NormCasePackagesPathList:
                a = os.path.basename(dirpathprevious)
                self.logger.debug("Reached Package Path.  Using previous directory: %s" % a)
                return a

            dirpathprevious = dirpath
            dirpath = os.path.dirname(dirpath)

        self.logger.error("Failed to find containing package for %s" % InputPath)
        self.logger.info("PackagePath is: %s" % os.pathsep.join(self.PackagePathList))
        self.logger.info("Workspace path is : %s" % self.WorkspacePath)
        return None

    def GetContainingModules(self, InputPath: str) -> list:
        '''Find the list of modules (infs) that file path is in
        for now just assume any inf in the same dir or if none
        then check parent dir.  If InputPath is not in the filesystem
        this function will try to return the likely containing module
        but if the entire module has been deleted this isn't possible.

        Note: The inputPath must be in the OS specific path form

        @param InputPath:  absolute path to file

        @ret list of abs path file paths for module infs
        '''

        self.logger.debug("GetContainingModules: %s" % InputPath)

        # if INF return self
        if fnmatch.fnmatch(InputPath.lower(), '*.inf'):
            return [InputPath]

        # Before checking the local filesystem for an INF
        # make sure filesystem has file or at least folder
        if not os.path.isfile(InputPath):
            logging.debug("InputPath doesn't exist in filesystem")

        modules = []
        # Check current dir
        dirpath = os.path.dirname(InputPath)
        if os.path.isdir(dirpath):
            for f in os.listdir(dirpath):
                if fnmatch.fnmatch(f.lower(), '*.inf'):
                    self.logger.debug("Found INF file in %s.  INf is: %s", dirpath, f)
                    modules.append(os.path.join(dirpath, f))

        # if didn't find any in current dir go to parent dir.
        # this handles cases like:
        # ModuleDir/
        #   Module.inf
        #   x64/
        #     file.c
        #
        if (len(modules) == 0):
            dirpath = os.path.dirname(dirpath)
            if os.path.isdir(dirpath):
                for f in os.listdir(dirpath):
                    if fnmatch.fnmatch(f.lower(), '*.inf'):
                        self.logger.debug("Found INF file in %s.  INf is: %s", dirpath, f)
                        modules.append(os.path.join(dirpath, f))

        return modules