File size: 22,788 Bytes
ad38045
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
��0:     @_deprecate_arguments(

1:         version="2.0",

2:         deprecated_args={"space_storage"},

3:         custom_message="Use `space_volumes` to mount volumes on a Space.",

4:     )

5:     @validate_hf_hub_args

6:     def create_repo(

7:         self,

8:         repo_id: str,

9:         *,

10:         token: str | bool | None = None,

11:         private: bool | None = None,

12:         visibility: RepoVisibility_T | None = None,

13:         repo_type: str | None = None,

14:         exist_ok: bool = False,

15:         resource_group_id: str | None = None,

16:         region: REPO_REGIONS | None = None,

17:         space_sdk: str | None = None,

18:         space_hardware: SpaceHardware | None = None,

19:         space_storage: SpaceStorage | None = None,

20:         space_sleep_time: int | None = None,

21:         space_secrets: list[dict[str, str]] | None = None,

22:         space_variables: list[dict[str, str]] | None = None,

23:         space_volumes: list[Volume] | None = None,

24:     ) -> RepoUrl:

25:         """Create an empty repo on the HuggingFace Hub.

26: 

27:         Args:

28:             repo_id (`str`):

29:                 A namespace (user or an organization) and a repo name separated

30:                 by a `/`.

31:             token (`bool` or `str`, *optional*):

32:                 A valid user access token (string). Defaults to the locally saved

33:                 token, which is the recommended method for authentication (see

34:                 https://huggingface.co/docs/huggingface_hub/quick-start#authentication).

35:                 To disable authentication, pass `False`.

36:             private (`bool`, *optional*):

37:                 Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. Cannot be passed together with `visibility`.

38:             visibility (`Literal["public", "private", "protected"]`, *optional*):

39:                 Visibility of the repo. Can be `"public"` or `"private"`, or `"protected"` for Spaces. If `None`

40:                 (default), the repo will be public unless the organization's default is private. This value is ignored

41:                 if the repo already exists.

42:             repo_type (`str`, *optional*):

43:                 Set to `"dataset"` or `"space"` if uploading to a dataset or

44:                 space, `None` or `"model"` if uploading to a model. Default is

45:                 `None`.

46:             exist_ok (`bool`, *optional*, defaults to `False`):

47:                 If `True`, do not raise an error if repo already exists.

48:             resource_group_id (`str`, *optional*):

49:                 Resource group in which to create the repo. Resource groups is only available for Enterprise Hub organizations and

50:                 allow to define which members of the organization can access the resource. The ID of a resource group

51:                 can be found in the URL of the resource's page on the Hub (e.g. `"66670e5163145ca562cb1988"`).

52:                 To learn more about resource groups, see https://huggingface.co/docs/hub/en/security-resource-groups.

53:             region (`Literal["us", "eu"]`, *optional*):

54:                 Cloud region in which to create the repo. Can be one of `"us"` or `"eu"`. If not specified, the repo will be

55:                 created in the default region. Requires Team plan or above.

56:             space_sdk (`str`, *optional*):

57:                 Choice of SDK to use if repo_type is "space". Can be "streamlit", "gradio", "docker", or "static".

58:             space_hardware (`SpaceHardware` or `str`, *optional*):

59:                 Choice of Hardware if repo_type is "space". See [`SpaceHardware`] for a complete list.

60:             space_storage (`SpaceStorage` or `str`, *optional*):

61:                 <Deprecated, use `set_space_volumes` instead> Choice of persistent storage tier. Example: `"small"`. See [`SpaceStorage`] for a complete list.

62:             space_sleep_time (`int`, *optional*):

63:                 Number of seconds of inactivity to wait before a Space is put to sleep. Set to `-1` if you don't want

64:                 your Space to sleep (default behavior for upgraded hardware). For free hardware, you can't configure

65:                 the sleep time (value is fixed to 48 hours of inactivity).

66:                 See https://huggingface.co/docs/hub/spaces-gpus#sleep-time for more details.

67:             space_secrets (`list[dict[str, str]]`, *optional*):

68:                 A list of secret keys to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional.

69:                 For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets.

70:             space_variables (`list[dict[str, str]]`, *optional*):

71:                 A list of public environment variables to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional.

72:                 For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets-and-environment-variables.

73:             space_volumes (`list[Volume]`, *optional*):

74:                 A list of [`Volume`] objects to mount in the Space at creation time. Each volume has a `type`

75:                 (`"bucket"`, `"model"`, `"dataset"`, or `"space"`), a `source` (repo or bucket ID), a `mount_path`

76:                 (path inside the container), and optional `revision`, `read_only`, and `path` fields.

77:                 Only applicable if repo_type is "space".

78: 

79:         Returns:

80:             [`RepoUrl`]: URL to the newly created repo. Value is a subclass of `str` containing

81:             attributes like `endpoint`, `repo_type` and `repo_id`.

82:         """

83:         organization, name = repo_id.split("/") if "/" in repo_id else (None, repo_id)

84: 

85:         path = f"{self.endpoint}/api/repos/create"

86: 

87:         if repo_type not in constants.REPO_TYPES_WITH_KERNEL:

88:             raise ValueError("Invalid repo type")

89: 

90:         resolved_visibility = _resolve_repo_visibility(private=private, visibility=visibility, repo_type=repo_type)

91: 

92:         payload: dict[str, Any] = {"name": name, "organization": organization}

93:         if resolved_visibility is not None:

94:             payload["visibility"] = resolved_visibility

95:         if repo_type is not None:

96:             payload["type"] = repo_type

97:         if repo_type == "space":

98:             if space_sdk is None:

99:                 raise ValueError(

100:                     "No space_sdk provided. `create_repo` expects space_sdk to be one"

101:                     f" of {constants.SPACES_SDK_TYPES} when repo_type is 'space'`"

102:                 )

103:             if space_sdk not in constants.SPACES_SDK_TYPES:

104:                 raise ValueError(f"Invalid space_sdk. Please choose one of {constants.SPACES_SDK_TYPES}.")

105:             payload["sdk"] = space_sdk

106: 

107:         if space_sdk is not None and repo_type != "space":

108:             warnings.warn("Ignoring provided space_sdk because repo_type is not 'space'.")

109: 

110:         space_args: list[tuple[str, str, Any]] = [

111:             # input arg, payload key, value

112:             ("space_hardware", "hardware", space_hardware),

113:             ("space_storage", "storageTier", space_storage),

114:             ("space_sleep_time", "sleepTimeSeconds", space_sleep_time),

115:             ("space_secrets", "secrets", space_secrets),

116:             ("space_variables", "variables", space_variables),

117:             ("space_volumes", "volumes", [v.to_dict() for v in space_volumes] if space_volumes else None),

118:         ]

119: 

120:         if repo_type == constants.REPO_TYPE_SPACE:

121:             for _, key, value in space_args:

122:                 if value is not None:

123:                     payload[key] = value

124:             if space_sleep_time is not None and space_hardware == SpaceHardware.CPU_BASIC:

125:                 warnings.warn(

126:                     "If your Space runs on the default 'cpu-basic' hardware, it will go to sleep if inactive for more"

127:                     " than 48 hours. This value is not configurable. If you don't want your Space to deactivate or if"

128:                     " you want to set a custom sleep time, you need to upgrade to a paid Hardware.",

129:                     UserWarning,

130:                 )

131:         else:

132:             if provided_space_args := [arg for arg, _, value in space_args if value is not None]:

133:                 warnings.warn(f"Ignoring provided {', '.join(provided_space_args)} because repo_type is not 'space'.")

134: 

135:         if resource_group_id is not None:

136:             payload["resourceGroupId"] = resource_group_id

137:         if region is not None:

138:             payload["region"] = region

139: 

140:         headers = self._build_hf_headers(token=token)

141:         while True:

142:             r = get_session().post(path, headers=headers, json=payload)

143:             if r.status_code == 409 and "Cannot create repo: another conflicting operation is in progress" in r.text:

144:                 # Since https://github.com/huggingface/moon-landing/pull/7272 (private repo), it is not possible to

145:                 # concurrently create repos on the Hub for a same user. This is rarely an issue, except when running

146:                 # tests. To avoid any inconvenience, we retry to create the repo for this specific error.

147:                 # NOTE: This could have being fixed directly in the tests but adding it here should fixed CIs for all

148:                 # dependent libraries.

149:                 # NOTE: If a fix is implemented server-side, we should be able to remove this retry mechanism.

150:                 logger.debug("Create repo failed due to a concurrency issue. Retrying...")

151:                 continue

152:             break

153: 

154:         try:

155:             hf_raise_for_status(r)

156:         except HfHubHTTPError as err:

157:             if exist_ok and err.response.status_code == 409:

158:                 # Repo already exists and `exist_ok=True`

159:                 pass

160:             elif exist_ok and err.response.status_code == 403:

161:                 # No write permission on the namespace but repo might already exist

162:                 try:

163:                     self.repo_info(repo_id=repo_id, repo_type=repo_type, token=token)

164:                     if repo_type is None or repo_type == constants.REPO_TYPE_MODEL:

165:                         return RepoUrl(f"{self.endpoint}/{repo_id}")

166:                     return RepoUrl(f"{self.endpoint}/{constants.REPO_TYPES_URL_PREFIXES[repo_type]}{repo_id}")

167:                 except HfHubHTTPError:

168:                     raise err

169:             else:

170:                 raise

171: 

172:         d = r.json()

173:         return RepoUrl(d["url"], endpoint=self.endpoint)

174: