user.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. # Copyright 2020 The HuggingFace Team. All rights reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import subprocess
  15. from argparse import ArgumentParser
  16. from typing import List, Union
  17. from huggingface_hub.hf_api import HfFolder, create_repo, whoami
  18. from requests.exceptions import HTTPError
  19. from . import BaseTransformersCLICommand
  20. class UserCommands(BaseTransformersCLICommand):
  21. @staticmethod
  22. def register_subcommand(parser: ArgumentParser):
  23. login_parser = parser.add_parser("login", help="Log in using the same credentials as on huggingface.co")
  24. login_parser.set_defaults(func=lambda args: LoginCommand(args))
  25. whoami_parser = parser.add_parser("whoami", help="Find out which huggingface.co account you are logged in as.")
  26. whoami_parser.set_defaults(func=lambda args: WhoamiCommand(args))
  27. logout_parser = parser.add_parser("logout", help="Log out")
  28. logout_parser.set_defaults(func=lambda args: LogoutCommand(args))
  29. # new system: git-based repo system
  30. repo_parser = parser.add_parser(
  31. "repo",
  32. help="Deprecated: use `huggingface-cli` instead. Commands to interact with your huggingface.co repos.",
  33. )
  34. repo_subparsers = repo_parser.add_subparsers(
  35. help="Deprecated: use `huggingface-cli` instead. huggingface.co repos related commands"
  36. )
  37. repo_create_parser = repo_subparsers.add_parser(
  38. "create", help="Deprecated: use `huggingface-cli` instead. Create a new repo on huggingface.co"
  39. )
  40. repo_create_parser.add_argument(
  41. "name",
  42. type=str,
  43. help="Name for your model's repo. Will be namespaced under your username to build the model id.",
  44. )
  45. repo_create_parser.add_argument("--organization", type=str, help="Optional: organization namespace.")
  46. repo_create_parser.add_argument("-y", "--yes", action="store_true", help="Optional: answer Yes to the prompt")
  47. repo_create_parser.set_defaults(func=lambda args: RepoCreateCommand(args))
  48. class ANSI:
  49. """
  50. Helper for en.wikipedia.org/wiki/ANSI_escape_code
  51. """
  52. _bold = "\u001b[1m"
  53. _red = "\u001b[31m"
  54. _gray = "\u001b[90m"
  55. _reset = "\u001b[0m"
  56. @classmethod
  57. def bold(cls, s):
  58. return f"{cls._bold}{s}{cls._reset}"
  59. @classmethod
  60. def red(cls, s):
  61. return f"{cls._bold}{cls._red}{s}{cls._reset}"
  62. @classmethod
  63. def gray(cls, s):
  64. return f"{cls._gray}{s}{cls._reset}"
  65. def tabulate(rows: List[List[Union[str, int]]], headers: List[str]) -> str:
  66. """
  67. Inspired by:
  68. - stackoverflow.com/a/8356620/593036
  69. - stackoverflow.com/questions/9535954/printing-lists-as-tabular-data
  70. """
  71. col_widths = [max(len(str(x)) for x in col) for col in zip(*rows, headers)]
  72. row_format = ("{{:{}}} " * len(headers)).format(*col_widths)
  73. lines = []
  74. lines.append(row_format.format(*headers))
  75. lines.append(row_format.format(*["-" * w for w in col_widths]))
  76. for row in rows:
  77. lines.append(row_format.format(*row))
  78. return "\n".join(lines)
  79. class BaseUserCommand:
  80. def __init__(self, args):
  81. self.args = args
  82. class LoginCommand(BaseUserCommand):
  83. def run(self):
  84. print(
  85. ANSI.red(
  86. "ERROR! `huggingface-cli login` uses an outdated login mechanism "
  87. "that is not compatible with the Hugging Face Hub backend anymore. "
  88. "Please use `huggingface-cli login instead."
  89. )
  90. )
  91. class WhoamiCommand(BaseUserCommand):
  92. def run(self):
  93. print(
  94. ANSI.red(
  95. "WARNING! `transformers-cli whoami` is deprecated and will be removed in v5. Please use "
  96. "`huggingface-cli whoami` instead."
  97. )
  98. )
  99. token = HfFolder.get_token()
  100. if token is None:
  101. print("Not logged in")
  102. exit()
  103. try:
  104. user, orgs = whoami(token)
  105. print(user)
  106. if orgs:
  107. print(ANSI.bold("orgs: "), ",".join(orgs))
  108. except HTTPError as e:
  109. print(e)
  110. print(ANSI.red(e.response.text))
  111. exit(1)
  112. class LogoutCommand(BaseUserCommand):
  113. def run(self):
  114. print(
  115. ANSI.red(
  116. "ERROR! `transformers-cli logout` uses an outdated logout mechanism "
  117. "that is not compatible with the Hugging Face Hub backend anymore. "
  118. "Please use `huggingface-cli logout instead."
  119. )
  120. )
  121. class RepoCreateCommand(BaseUserCommand):
  122. def run(self):
  123. print(
  124. ANSI.red(
  125. "WARNING! Managing repositories through transformers-cli is deprecated. "
  126. "Please use `huggingface-cli` instead."
  127. )
  128. )
  129. token = HfFolder.get_token()
  130. if token is None:
  131. print("Not logged in")
  132. exit(1)
  133. try:
  134. stdout = subprocess.check_output(["git", "--version"]).decode("utf-8")
  135. print(ANSI.gray(stdout.strip()))
  136. except FileNotFoundError:
  137. print("Looks like you do not have git installed, please install.")
  138. try:
  139. stdout = subprocess.check_output(["git-lfs", "--version"]).decode("utf-8")
  140. print(ANSI.gray(stdout.strip()))
  141. except FileNotFoundError:
  142. print(
  143. ANSI.red(
  144. "Looks like you do not have git-lfs installed, please install."
  145. " You can install from https://git-lfs.github.com/."
  146. " Then run `git lfs install` (you only have to do this once)."
  147. )
  148. )
  149. print("")
  150. user, _ = whoami(token)
  151. namespace = self.args.organization if self.args.organization is not None else user
  152. full_name = f"{namespace}/{self.args.name}"
  153. print(f"You are about to create {ANSI.bold(full_name)}")
  154. if not self.args.yes:
  155. choice = input("Proceed? [Y/n] ").lower()
  156. if not (choice == "" or choice == "y" or choice == "yes"):
  157. print("Abort")
  158. exit()
  159. try:
  160. url = create_repo(repo_id=full_name, token=token)
  161. except HTTPError as e:
  162. print(e)
  163. print(ANSI.red(e.response.text))
  164. exit(1)
  165. print("\nYour repo now lives at:")
  166. print(f" {ANSI.bold(url)}")
  167. print("\nYou can clone it locally with the command below, and commit/push as usual.")
  168. print(f"\n git clone {url}")
  169. print("")