# Copyright 2020 The HuggingFace Team. All rights reserved.
#
# 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.

# ***********
# `huggingface_hub` init has 2 modes:
# - Normal usage:
#       If imported to use it, all modules and functions are lazy-loaded. This means
#       they exist at top level in module but are imported only the first time they are
#       used. This way, `from huggingface_hub import something` will import `something`
#       quickly without the hassle of importing all the features from `huggingface_hub`.
# - Static check:
#       If statically analyzed, all modules and functions are loaded normally. This way
#       static typing check works properly as well as autocomplete in text editors and
#       IDEs.
#
# The static model imports are done inside the `if TYPE_CHECKING:` statement at
# the bottom of this file. Since module/functions imports are duplicated, it is
# mandatory to make sure to add them twice when adding one. This is checked in the
# `make quality` command.
#
# To update the static imports, please run the following command and commit the changes.
# ```
# # Use script
# python utils/check_static_imports.py --update-file
#
# # Or run style on codebase
# make style
# ```
#
# ***********
# Lazy loader vendored from https://github.com/scientific-python/lazy_loader
import importlib
import os
import sys
from typing import TYPE_CHECKING


__version__ = "0.11.1"

# Alphabetical order of definitions is ensured in tests
# WARNING: any comment added in this dictionary definition will be lost when
# re-generating the file !
_SUBMOD_ATTRS = {
    "_login": [
        "interpreter_login",
        "login",
        "logout",
        "notebook_login",
    ],
    "_snapshot_download": [
        "snapshot_download",
    ],
    "community": [
        "Discussion",
        "DiscussionComment",
        "DiscussionCommit",
        "DiscussionEvent",
        "DiscussionStatusChange",
        "DiscussionTitleChange",
        "DiscussionWithDetails",
    ],
    "constants": [
        "CONFIG_NAME",
        "FLAX_WEIGHTS_NAME",
        "HUGGINGFACE_CO_URL_HOME",
        "HUGGINGFACE_CO_URL_TEMPLATE",
        "PYTORCH_WEIGHTS_NAME",
        "REPO_TYPE_DATASET",
        "REPO_TYPE_MODEL",
        "REPO_TYPE_SPACE",
        "TF2_WEIGHTS_NAME",
        "TF_WEIGHTS_NAME",
    ],
    "fastai_utils": [
        "_save_pretrained_fastai",
        "from_pretrained_fastai",
        "push_to_hub_fastai",
    ],
    "file_download": [
        "HfFileMetadata",
        "cached_download",
        "get_hf_file_metadata",
        "hf_hub_download",
        "hf_hub_url",
        "try_to_load_from_cache",
    ],
    "hf_api": [
        "CommitInfo",
        "CommitOperation",
        "CommitOperationAdd",
        "CommitOperationDelete",
        "DatasetSearchArguments",
        "HfApi",
        "ModelSearchArguments",
        "change_discussion_status",
        "comment_discussion",
        "create_branch",
        "create_commit",
        "create_discussion",
        "create_pull_request",
        "create_repo",
        "create_tag",
        "dataset_info",
        "delete_branch",
        "delete_file",
        "delete_folder",
        "delete_repo",
        "delete_tag",
        "edit_discussion_comment",
        "get_dataset_tags",
        "get_discussion_details",
        "get_full_repo_name",
        "get_model_tags",
        "get_repo_discussions",
        "list_datasets",
        "list_metrics",
        "list_models",
        "list_repo_files",
        "list_spaces",
        "merge_pull_request",
        "model_info",
        "move_repo",
        "rename_discussion",
        "repo_type_and_id_from_hf_id",
        "set_access_token",
        "space_info",
        "unset_access_token",
        "update_repo_visibility",
        "upload_file",
        "upload_folder",
        "whoami",
    ],
    "hub_mixin": [
        "ModelHubMixin",
        "PyTorchModelHubMixin",
    ],
    "inference_api": [
        "InferenceApi",
    ],
    "keras_mixin": [
        "KerasModelHubMixin",
        "from_pretrained_keras",
        "push_to_hub_keras",
        "save_pretrained_keras",
    ],
    "repocard": [
        "DatasetCard",
        "ModelCard",
        "metadata_eval_result",
        "metadata_load",
        "metadata_save",
        "metadata_update",
    ],
    "repocard_data": [
        "CardData",
        "DatasetCardData",
        "EvalResult",
        "ModelCardData",
    ],
    "repository": [
        "Repository",
    ],
    "utils": [
        "CacheNotFound",
        "CachedFileInfo",
        "CachedRepoInfo",
        "CachedRevisionInfo",
        "CorruptedCacheException",
        "DeleteCacheStrategy",
        "HFCacheInfo",
        "HfFolder",
        "cached_assets_path",
        "dump_environment_info",
        "logging",
        "scan_cache_dir",
    ],
    "utils.endpoint_helpers": [
        "DatasetFilter",
        "ModelFilter",
    ],
}


def _attach(package_name, submodules=None, submod_attrs=None):
    """Attach lazily loaded submodules, functions, or other attributes.

    Typically, modules import submodules and attributes as follows:

    ```py
    import mysubmodule
    import anothersubmodule

    from .foo import someattr
    ```

    The idea is to replace a package's `__getattr__`, `__dir__`, and
    `__all__`, such that all imports work exactly the way they would
    with normal imports, except that the import occurs upon first use.

    The typical way to call this function, replacing the above imports, is:

    ```python
    __getattr__, __dir__, __all__ = lazy.attach(
        __name__,
        ['mysubmodule', 'anothersubmodule'],
        {'foo': ['someattr']}
    )
    ```
    This functionality requires Python 3.7 or higher.

    Args:
        package_name (`str`):
            Typically use `__name__`.
        submodules (`set`):
            List of submodules to attach.
        submod_attrs (`dict`):
            Dictionary of submodule -> list of attributes / functions.
            These attributes are imported as they are used.

    Returns:
        __getattr__, __dir__, __all__

    """
    if submod_attrs is None:
        submod_attrs = {}

    if submodules is None:
        submodules = set()
    else:
        submodules = set(submodules)

    attr_to_modules = {
        attr: mod for mod, attrs in submod_attrs.items() for attr in attrs
    }

    __all__ = list(submodules | attr_to_modules.keys())

    def __getattr__(name):
        if name in submodules:
            return importlib.import_module(f"{package_name}.{name}")
        elif name in attr_to_modules:
            submod_path = f"{package_name}.{attr_to_modules[name]}"
            submod = importlib.import_module(submod_path)
            attr = getattr(submod, name)

            # If the attribute lives in a file (module) with the same
            # name as the attribute, ensure that the attribute and *not*
            # the module is accessible on the package.
            if name == attr_to_modules[name]:
                pkg = sys.modules[package_name]
                pkg.__dict__[name] = attr

            return attr
        else:
            raise AttributeError(f"No {package_name} attribute {name}")

    def __dir__():
        return __all__

    if os.environ.get("EAGER_IMPORT", ""):
        for attr in set(attr_to_modules.keys()) | submodules:
            __getattr__(attr)

    return __getattr__, __dir__, list(__all__)


__getattr__, __dir__, __all__ = _attach(
    __name__, submodules=[], submod_attrs=_SUBMOD_ATTRS
)

# WARNING: any content below this statement is generated automatically. Any manual edit
# will be lost when re-generating this file !
#
# To update the static imports, please run the following command and commit the changes.
# ```
# # Use script
# python utils/check_static_imports.py --update-file
#
# # Or run style on codebase
# make style
# ```
if TYPE_CHECKING:  # pragma: no cover
    from ._login import interpreter_login  # noqa: F401
    from ._login import login  # noqa: F401
    from ._login import logout  # noqa: F401
    from ._login import notebook_login  # noqa: F401
    from ._snapshot_download import snapshot_download  # noqa: F401
    from .community import Discussion  # noqa: F401
    from .community import DiscussionComment  # noqa: F401
    from .community import DiscussionCommit  # noqa: F401
    from .community import DiscussionEvent  # noqa: F401
    from .community import DiscussionStatusChange  # noqa: F401
    from .community import DiscussionTitleChange  # noqa: F401
    from .community import DiscussionWithDetails  # noqa: F401
    from .constants import CONFIG_NAME  # noqa: F401
    from .constants import FLAX_WEIGHTS_NAME  # noqa: F401
    from .constants import HUGGINGFACE_CO_URL_HOME  # noqa: F401
    from .constants import HUGGINGFACE_CO_URL_TEMPLATE  # noqa: F401
    from .constants import PYTORCH_WEIGHTS_NAME  # noqa: F401
    from .constants import REPO_TYPE_DATASET  # noqa: F401
    from .constants import REPO_TYPE_MODEL  # noqa: F401
    from .constants import REPO_TYPE_SPACE  # noqa: F401
    from .constants import TF2_WEIGHTS_NAME  # noqa: F401
    from .constants import TF_WEIGHTS_NAME  # noqa: F401
    from .fastai_utils import _save_pretrained_fastai  # noqa: F401
    from .fastai_utils import from_pretrained_fastai  # noqa: F401
    from .fastai_utils import push_to_hub_fastai  # noqa: F401
    from .file_download import HfFileMetadata  # noqa: F401
    from .file_download import cached_download  # noqa: F401
    from .file_download import get_hf_file_metadata  # noqa: F401
    from .file_download import hf_hub_download  # noqa: F401
    from .file_download import hf_hub_url  # noqa: F401
    from .file_download import try_to_load_from_cache  # noqa: F401
    from .hf_api import CommitInfo  # noqa: F401
    from .hf_api import CommitOperation  # noqa: F401
    from .hf_api import CommitOperationAdd  # noqa: F401
    from .hf_api import CommitOperationDelete  # noqa: F401
    from .hf_api import DatasetSearchArguments  # noqa: F401
    from .hf_api import HfApi  # noqa: F401
    from .hf_api import ModelSearchArguments  # noqa: F401
    from .hf_api import change_discussion_status  # noqa: F401
    from .hf_api import comment_discussion  # noqa: F401
    from .hf_api import create_branch  # noqa: F401
    from .hf_api import create_commit  # noqa: F401
    from .hf_api import create_discussion  # noqa: F401
    from .hf_api import create_pull_request  # noqa: F401
    from .hf_api import create_repo  # noqa: F401
    from .hf_api import create_tag  # noqa: F401
    from .hf_api import dataset_info  # noqa: F401
    from .hf_api import delete_branch  # noqa: F401
    from .hf_api import delete_file  # noqa: F401
    from .hf_api import delete_folder  # noqa: F401
    from .hf_api import delete_repo  # noqa: F401
    from .hf_api import delete_tag  # noqa: F401
    from .hf_api import edit_discussion_comment  # noqa: F401
    from .hf_api import get_dataset_tags  # noqa: F401
    from .hf_api import get_discussion_details  # noqa: F401
    from .hf_api import get_full_repo_name  # noqa: F401
    from .hf_api import get_model_tags  # noqa: F401
    from .hf_api import get_repo_discussions  # noqa: F401
    from .hf_api import list_datasets  # noqa: F401
    from .hf_api import list_metrics  # noqa: F401
    from .hf_api import list_models  # noqa: F401
    from .hf_api import list_repo_files  # noqa: F401
    from .hf_api import list_spaces  # noqa: F401
    from .hf_api import merge_pull_request  # noqa: F401
    from .hf_api import model_info  # noqa: F401
    from .hf_api import move_repo  # noqa: F401
    from .hf_api import rename_discussion  # noqa: F401
    from .hf_api import repo_type_and_id_from_hf_id  # noqa: F401
    from .hf_api import set_access_token  # noqa: F401
    from .hf_api import space_info  # noqa: F401
    from .hf_api import unset_access_token  # noqa: F401
    from .hf_api import update_repo_visibility  # noqa: F401
    from .hf_api import upload_file  # noqa: F401
    from .hf_api import upload_folder  # noqa: F401
    from .hf_api import whoami  # noqa: F401
    from .hub_mixin import ModelHubMixin  # noqa: F401
    from .hub_mixin import PyTorchModelHubMixin  # noqa: F401
    from .inference_api import InferenceApi  # noqa: F401
    from .keras_mixin import KerasModelHubMixin  # noqa: F401
    from .keras_mixin import from_pretrained_keras  # noqa: F401
    from .keras_mixin import push_to_hub_keras  # noqa: F401
    from .keras_mixin import save_pretrained_keras  # noqa: F401
    from .repocard import DatasetCard  # noqa: F401
    from .repocard import ModelCard  # noqa: F401
    from .repocard import metadata_eval_result  # noqa: F401
    from .repocard import metadata_load  # noqa: F401
    from .repocard import metadata_save  # noqa: F401
    from .repocard import metadata_update  # noqa: F401
    from .repocard_data import CardData  # noqa: F401
    from .repocard_data import DatasetCardData  # noqa: F401
    from .repocard_data import EvalResult  # noqa: F401
    from .repocard_data import ModelCardData  # noqa: F401
    from .repository import Repository  # noqa: F401
    from .utils import CachedFileInfo  # noqa: F401
    from .utils import CachedRepoInfo  # noqa: F401
    from .utils import CachedRevisionInfo  # noqa: F401
    from .utils import CacheNotFound  # noqa: F401
    from .utils import CorruptedCacheException  # noqa: F401
    from .utils import DeleteCacheStrategy  # noqa: F401
    from .utils import HFCacheInfo  # noqa: F401
    from .utils import HfFolder  # noqa: F401
    from .utils import cached_assets_path  # noqa: F401
    from .utils import dump_environment_info  # noqa: F401
    from .utils import logging  # noqa: F401
    from .utils import scan_cache_dir  # noqa: F401
    from .utils.endpoint_helpers import DatasetFilter  # noqa: F401
    from .utils.endpoint_helpers import ModelFilter  # noqa: F401
