File size: 24,084 Bytes
3d65c27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# πŸš€ Welcome to the Hugging Face Uploader Notebook!\n",
    "\n",
    "This notebook provides a user-friendly tool for uploading files directly to your Hugging Face repositories. Here's how to get started:\n",
    "\n",
    "**πŸ”‘ Initial Setup (One Time Only)**\n",
    "\n",
    "1.  **Authenticate:**\n",
    "    *   Run the `notebook_login()` cell *once* to securely store your Hugging Face API token.\n",
    "    *   **Important:** For security, avoid sharing your notebook file or system state after you have run `notebook_login()`. Do not commit your notebook file to a shared repo, as this could expose your API token.\n",
    "\n",
    "**πŸ—‚οΈ Using the Uploader**\n",
    "\n",
    "1.  **Repository Details:**\n",
    "    *   Enter your Hugging Face Organization or Username in the \"Owner\" field.\n",
    "    *   Enter your repository name in the \"Repo\" field.\n",
    "\n",
    "2.  **Directory Selection:**\n",
    "    *  Enter a directory path where your files are located.\n",
    "    *  Select the 'Update Dir' button to set that path.\n",
    "\n",
    "3.  **File Selection:**\n",
    "    *   Select the appropriate file type from the dropdown menu.\n",
    "    *   Select the files you want to upload from the list. You can sort them by name or date modified.\n",
    "\n",
    "4.  **Commit Message (Optional):**\n",
    "    *   Add a commit message to your upload, or use the default message.\n",
    "\n",
    "5.  **Upload Options:**\n",
    "    *   Choose whether to create a pull request or upload directly to the main branch.\n",
    "    *   Select whether to clear the output after a successful upload.\n",
    "\n",
    "6.  **Start Upload:**\n",
    "    *   Click the \"⬆️ Upload\" button.\n",
    "\n",
    "**πŸ’‘ Important Notes**\n",
    "\n",
    "*   **Direct Uploads:** This uploader uses the Hugging Face API for direct file uploads, bypassing the need for traditional Git operations for core functionality.\n",
    "*   **Git LFS:** Most users will not need to interact with Git or Git LFS. If you need to clone or push changes to a repository *outside this notebook*, you will require a separate Git credential setup (e.g., your operating system's credential manager or SSH keys).  This is separate from your Hugging Face API token, and you should not share any git credentials in your notebook.\n",
    "*   **Troubleshooting:** If you encounter any issues, please review the steps, or double-check that you have write access to the repository, and that your API token has the correct scope of access.\n",
    "\n",
    "**πŸ“£ Updates & Community**\n",
    "\n",
    "*   This tool will continue to be updated.\n",
    "*   For the latest patches, fixes, and community contributions, visit [https://github.com/duskfallcrew/HuggingFace_Backup](https://github.com/duskfallcrew/HuggingFace_Backup)\n",
    "\n",
    "We hope this notebook makes your Hugging Face uploads easier! If you have any questions or suggestions, please reach out."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q huggingface_hub ipywidgets tqdm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Xs1mb1VKLuUW"
   },
   "source": [
    "# ✨ Connecting to Hugging Face: Authentication Required\n",
    "\n",
    "To upload files to Hugging Face using this notebook, you'll need to authenticate using your Hugging Face API token. This token acts as your secure access key to the Hugging Face Hub.\n",
    "\n",
    "**πŸ”‘ Obtaining Your API Token**\n",
    "\n",
    "1.  **Go to Your Settings:** Navigate to your [Hugging Face account settings](https://huggingface.co/settings/tokens).\n",
    "2.  **Access Tokens Section:** Find the \"Access Tokens\" section.\n",
    "3.  **Create or Copy Token:**\n",
    "    *   If you don't have one already, create a new access token.\n",
    "    *   Copy your existing access token.\n",
    "\n",
    "**πŸ”’ Logging In**\n",
    "\n",
    "1.  **Run the Cell:** Execute the cell below this section.\n",
    "2.  **Paste Token:** When prompted, paste your Hugging Face API token into the input field.\n",
    "3.  **Confirm:** Press `Enter` to complete the login process. No characters will be displayed as you type your token.\n",
    "    *   **Security Note:** This ensures your token is kept private while pasting.\n",
    "\n",
    "**Important Notes**\n",
    "\n",
    "*   **Purpose:** This login step authorizes your notebook environment to interact with the Hugging Face Hub. This is required for uploading your models and data.\n",
    "*   **Session-Based:** You will need to perform this login procedure each time you restart the notebook or start a new session (the token is stored locally on your computer, but not in the notebook, and it doesn't persist between sessions).\n",
    "*  **Security:** After you have logged in using `notebook_login()`, **do not** share your notebook or your system state with untrusted users, and do not commit your notebook to a shared repository, as this could compromise your API token.\n",
    "\n",
    "After completing this step, you'll be ready to use the upload functionality of this notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b8aa868174ad469e86777458ea77c214",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value='<center> <img\\nsrc=https://huggingface.co/front/assets/huggingface_logo-noborder.sv…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from huggingface_hub import notebook_login\n",
    "import os\n",
    "notebook_login()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# πŸš€ Using the Hugging Face File Uploader\n",
    "\n",
    "To upload files to your Hugging Face repository, please follow these steps:\n",
    "\n",
    "**Before you start**: You **must have already completed the following:**\n",
    "\n",
    "  * You have authenticated with Hugging Face by running the `notebook_login()` cell located at the start of the notebook.\n",
    "  * You have created your repository on the Hugging Face Hub.\n",
    "\n",
    "**Using the Uploader**\n",
    "\n",
    "1.  **Repository Details:**\n",
    "    *   Enter your Hugging Face Organization or Username in the \"Owner\" field.\n",
    "    *   Enter your repository name in the \"Repo\" field.\n",
    "\n",
    "2.  **Directory Selection**\n",
    "     *  Enter a directory path where your files are located.\n",
    "     *  Select the 'Update Dir' button to set that path.\n",
    "\n",
    "3.  **File Selection:**\n",
    "    *   Select the appropriate file type from the dropdown menu (e.g., SafeTensors, PyTorch).\n",
    "    *   Choose how you want to sort your files (by name or date modified).\n",
    "    *   Select the files you wish to upload from the list.\n",
    "\n",
    "4.  **Upload Settings:**\n",
    "    *   Enable \"Create Pull Request\" if you want to submit your changes through a pull request, otherwise the changes will be made directly to the main branch of your repo.\n",
    "    *   Click the \"Upload\" button to start the upload process.\n",
    "\n",
    "**Status and Updates**\n",
    "\n",
    "*   The uploader will provide progress messages during the upload process.\n",
    "*   Any errors will be reported with suggestions on how to fix them.\n",
    "\n",
    "**Reusing the Uploader**\n",
    "\n",
    "*   You can repeat these steps to upload additional files to the same repository."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "cellView": "form",
    "id": "J851eLx6Ii3h"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "075b7bb0b71e4f0aaa272bfb20fbcebd",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(HTML(value='<b>πŸ“š Repository Details</b>'), HBox(children=(Text(value='', description='Owner:', …"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import glob\n",
    "import os\n",
    "from pathlib import Path\n",
    "from huggingface_hub import HfApi\n",
    "from ipywidgets import Text, Dropdown, Button, SelectMultiple, VBox, HBox, Output, Layout, Checkbox, HTML, Textarea, Label, IntProgress\n",
    "from IPython.display import display, clear_output\n",
    "import time\n",
    "from tqdm import tqdm\n",
    "\n",
    "class HuggingFaceUploader:\n",
    "    def __init__(self):\n",
    "        self.api = HfApi()\n",
    "        self.file_types = [\n",
    "            # AI Model Files πŸ€–\n",
    "            ('SafeTensors', 'safetensors'),\n",
    "            ('PyTorch Models', 'pt'),\n",
    "            ('PyTorch Legacy', 'pth'),\n",
    "            ('ONNX Models', 'onnx'),\n",
    "            ('TensorFlow Models', 'pb'),\n",
    "            ('Keras Models', 'h5'),\n",
    "\n",
    "            # Checkpoint Files 🎯\n",
    "            ('Checkpoints', 'ckpt'),\n",
    "            ('Binary Files', 'bin'),\n",
    "\n",
    "            # Config & Data Files πŸ“\n",
    "            ('JSON Files', 'json'),\n",
    "            ('YAML Files', 'yaml'),\n",
    "            ('YAML Alt', 'yml'),\n",
    "            ('Text Files', 'txt'),\n",
    "            ('CSV Files', 'csv'),\n",
    "            ('Pickle Files', 'pkl'),\n",
    "\n",
    "            # Image Files 🎨\n",
    "            ('PNG Images', 'png'),\n",
    "            ('JPEG Images', 'jpg'),\n",
    "            ('JPEG Alt', 'jpeg'),\n",
    "            ('WebP Images', 'webp'),\n",
    "            ('GIF Images', 'gif'),\n",
    "\n",
    "            # Archive Files πŸ“¦\n",
    "            ('ZIP Archives', 'zip'),\n",
    "            ('TAR Files', 'tar'),\n",
    "            ('GZ Archives', 'gz')\n",
    "        ]\n",
    "        self.current_directory = os.getcwd()\n",
    "        self._create_widgets()\n",
    "        self._bind_events()\n",
    "\n",
    "\n",
    "    def _create_widgets(self):\n",
    "        # Repository info section\n",
    "        self.repo_info = HTML(value=\"<b>πŸ“š Repository Details</b>\")\n",
    "        self.org_name = Text(\n",
    "            placeholder='Organization or Username',\n",
    "            description='Owner:',\n",
    "            style={'description_width': 'initial'}\n",
    "        )\n",
    "        self.repo_name = Text(\n",
    "            placeholder='Repository Name',\n",
    "            description='Repo:',\n",
    "            style={'description_width': 'initial'}\n",
    "        )\n",
    "\n",
    "        # File handling section\n",
    "        self.file_section = HTML(value=\"<b>πŸ—‚οΈ File Selection</b>\")\n",
    "        self.file_type = Dropdown(\n",
    "            options=self.file_types,\n",
    "            value='safetensors',\n",
    "            description='File Type:',\n",
    "            style={'description_width': 'initial'}\n",
    "        )\n",
    "        self.sort_by = Dropdown(\n",
    "            options=['name', 'date'],\n",
    "            value='name',\n",
    "            description='Sort By:'\n",
    "        )\n",
    "        self.directory_label = Label(value=f\"Current Directory: {self.current_directory}\")\n",
    "        self.directory_text = Text(\n",
    "             value=self.current_directory,\n",
    "            description=\"Path:\",\n",
    "            style={'description_width': 'initial'},\n",
    "            layout=Layout(width=\"400px\")\n",
    "        )\n",
    "        self.directory_update_btn = Button(\n",
    "            description='πŸ”„ Update Dir',\n",
    "            button_style='info',\n",
    "            tooltip='Refresh directory'\n",
    "        )\n",
    "\n",
    "\n",
    "        # Custom commit message\n",
    "        self.commit_section = HTML(value=\"<b>πŸ’­ Commit Details</b>\")\n",
    "        self.commit_msg = Textarea(\n",
    "            value=\"Upload with Earth & Dusk Huggingface πŸ€— Backup\",\n",
    "            placeholder='Enter your commit message (optional)',\n",
    "            description='Message:',\n",
    "            layout=Layout(width='400px', height='60px')\n",
    "        )\n",
    "\n",
    "        # Upload options section\n",
    "        self.upload_section = HTML(value=\"<b>πŸš€ Upload Settings</b>\")\n",
    "        self.create_pr = Checkbox(\n",
    "            value=False,\n",
    "            description='Create Pull Request',\n",
    "            indent=False,\n",
    "            tooltip='When checked, creates a Pull Request instead of direct upload'\n",
    "        )\n",
    "        self.clear_after = Checkbox(\n",
    "            value=True,\n",
    "            description='Clear output after upload',\n",
    "            indent=False,\n",
    "            tooltip='Clears output area after successful upload'\n",
    "        )\n",
    "\n",
    "        # Progress tracking\n",
    "        self.progress_text = HTML(value=\"\")\n",
    "\n",
    "        # Action buttons with style\n",
    "        self.update_btn = Button(\n",
    "            description='πŸ”„ Update Files',\n",
    "            button_style='info',\n",
    "            tooltip='Refresh file list'\n",
    "        )\n",
    "        self.upload_btn = Button(\n",
    "            description='⬆️ Upload',\n",
    "            button_style='success',\n",
    "            tooltip='Start upload process',\n",
    "             layout=Layout(width='auto', height='auto'),\n",
    "        )\n",
    "        self.clear_btn = Button(\n",
    "            description='🧹 Clear Output',\n",
    "            button_style='warning',\n",
    "            tooltip='Clear output area'\n",
    "        )\n",
    "\n",
    "        # File selector and output\n",
    "        self.ckpt_picker = SelectMultiple(\n",
    "            options=[],\n",
    "            layout=Layout(width=\"600px\", height=\"200px\")\n",
    "        )\n",
    "        self.out = Output(layout=Layout(padding='10px'))\n",
    "        \n",
    "         # Create debug output:\n",
    "        self.debug_output = Output()\n",
    "        self.debug_box = VBox([HTML(value=\"<b style='color: #2ecc71;'>Debug Output</b>\"), self.debug_output],\n",
    "                           layout=Layout(border='2px solid #2ecc71', padding='10px', margin_top='10px'))\n",
    "        self.debug_toggle = Checkbox(\n",
    "            value=False,\n",
    "            description='Show Debug',\n",
    "            indent=False,\n",
    "            tooltip='Show debug information'\n",
    "        )\n",
    "        self.debug_box.layout.visibility = 'hidden'\n",
    "\n",
    "\n",
    "    def _bind_events(self):\n",
    "        self.update_btn.on_click(self._update_files)\n",
    "        self.upload_btn.on_click(self._upload_ckpts)\n",
    "        self.clear_btn.on_click(lambda _: self.out.clear_output())\n",
    "        self.file_type.observe(self._update_files, names='value')\n",
    "        self.directory_update_btn.on_click(self._update_directory)\n",
    "        self.debug_toggle.observe(self._toggle_debug, names='value')\n",
    "\n",
    "    def _toggle_debug(self,_):\n",
    "      if self.debug_toggle.value == True:\n",
    "        self.debug_box.layout.visibility = 'visible'\n",
    "      else:\n",
    "        self.debug_box.layout.visibility = 'hidden'\n",
    "\n",
    "\n",
    "    def _update_directory(self,_):\n",
    "        new_dir = self.directory_text.value\n",
    "        if os.path.isdir(new_dir):\n",
    "            self.current_directory = new_dir\n",
    "            self.directory_label.value = f\"Current Directory: {self.current_directory}\"\n",
    "            self._update_files(None)\n",
    "        else:\n",
    "            with self.out:\n",
    "              print(\"❌ Invalid Directory\")\n",
    "\n",
    "    def _update_files(self, _):\n",
    "         file_extension = self.file_type.value\n",
    "         try:\n",
    "            # Glob files based on file extension\n",
    "            all_files = glob.glob(os.path.join(self.current_directory, f\"*.{file_extension}\"))\n",
    "\n",
    "            with self.debug_output:\n",
    "              print(f\"DEBUG _update_files: File type is {file_extension}\")\n",
    "              print(f\"DEBUG _update_files: All files found by glob: {all_files}\")\n",
    "\n",
    "            # Filter out symlinks, old files and ignore patterns\n",
    "            filtered_files = []\n",
    "            for file_path in all_files:\n",
    "              if os.path.islink(file_path):\n",
    "                 with self.debug_output:\n",
    "                    print(f\"DEBUG _update_files: Skipping symlink {file_path}\")\n",
    "                 continue\n",
    "              if not os.path.isfile(file_path):\n",
    "                  with self.debug_output:\n",
    "                     print(f\"DEBUG _update_files: Skipping non file {file_path}\")\n",
    "                  continue\n",
    "\n",
    "              filtered_files.append(file_path)\n",
    "            \n",
    "            # Sort the files\n",
    "            all_ckpts = sorted(\n",
    "                filtered_files,\n",
    "                 key=os.path.getmtime if self.sort_by.value == 'date' else str\n",
    "            )\n",
    "\n",
    "            self.ckpt_picker.options = all_ckpts\n",
    "\n",
    "            with self.out:\n",
    "                 print(f\"✨ Found {len(all_ckpts)} {file_extension} files in {self.current_directory}\")\n",
    "\n",
    "         except Exception as e:\n",
    "            with self.out:\n",
    "                print(f\"❌ Error listing files: {str(e)}\")\n",
    "\n",
    "\n",
    "    def _format_size(self, size):\n",
    "        for unit in ['B', 'KB', 'MB', 'GB']:\n",
    "            if size < 1024:\n",
    "                return f\"{size:.2f} {unit}\"\n",
    "            size /= 1024\n",
    "        return f\"{size:.2f} TB\"\n",
    "\n",
    "    def _print_file_info(self, file_path, file_size, index, total):\n",
    "         with self.out:\n",
    "                print(f\"πŸ“¦ File {index}/{total}: {file_path} ({self._format_size(file_size)})\")\n",
    "\n",
    "\n",
    "    def _upload_ckpts(self, _):\n",
    "        if not self.org_name.value or not self.repo_name.value:\n",
    "            with self.out:\n",
    "                print(\"❗ Please fill in both Organization/Username and Repository name\")\n",
    "                return\n",
    "\n",
    "        repo_id = f\"{self.org_name.value}/{self.repo_name.value}\"\n",
    "        selected_files = self.ckpt_picker.value\n",
    "        total_files = len(selected_files)\n",
    "\n",
    "        with self.out:\n",
    "            if not selected_files:\n",
    "                print(\"πŸ“ Nothing selected for upload. Please select files from the list.\")\n",
    "                return\n",
    "\n",
    "            print(f\"🎯 Starting upload to: huggingface.co/{repo_id}\")\n",
    "\n",
    "        commit_msg = self.commit_msg.value if self.commit_msg.value else \"Uploaded with Earth & Dusk Huggingface πŸ€— Backup\"\n",
    "\n",
    "        with self.debug_output:\n",
    "            print(f\"DEBUG TQDM: Is TQDM working? This should be above the progress bar.\")\n",
    "\n",
    "        progress_bar = IntProgress( # Create a progress bar for this upload\n",
    "            value=0,\n",
    "            min=0,\n",
    "            max=total_files,\n",
    "            description='Upload Progress:',\n",
    "            style={'description_width': 'initial'},\n",
    "            layout=Layout(width=\"400px\"),\n",
    "          )\n",
    "        display(progress_bar)  # Display progress bar\n",
    "\n",
    "        for idx, ckpt in enumerate(selected_files, 1):\n",
    "            try:\n",
    "                file_size = os.path.getsize(ckpt)\n",
    "                self._print_file_info(ckpt, file_size, idx, total_files)\n",
    "                start_time = time.time()\n",
    "                with self.debug_output:\n",
    "                   print(f\"πŸš€ Attempting upload of {ckpt}\")\n",
    "                response = self.api.upload_file(\n",
    "                    path_or_fileobj=ckpt,\n",
    "                    path_in_repo=os.path.basename(ckpt),\n",
    "                    repo_id=repo_id,\n",
    "                    repo_type=None,\n",
    "                    create_pr=self.create_pr.value,\n",
    "                    commit_message=commit_msg\n",
    "                )\n",
    "                with self.debug_output:\n",
    "                    print(f\"βœ… Upload Response: {response}\")\n",
    "                duration = time.time() - start_time\n",
    "                with self.out:\n",
    "                   print(f\"βœ… Upload completed in {duration:.1f} seconds\")\n",
    "                   display(response)\n",
    "\n",
    "\n",
    "                progress_bar.value = idx\n",
    "                display(progress_bar) # Force a render of the progress bar\n",
    "            except Exception as e:\n",
    "                 with self.out:\n",
    "                    print(f\"❌ Error uploading {ckpt}: {str(e)}\")\n",
    "                 continue\n",
    "\n",
    "\n",
    "        with self.out:\n",
    "            print(\"\\n✨ All uploads completed! ✨\")\n",
    "            if self.create_pr.value:\n",
    "                print(\"πŸŽ‰ Check your repository for the new Pull Request!\")\n",
    "            else:\n",
    "                print(\"πŸŽ‰ Files have been uploaded directly to your repository!\")\n",
    "\n",
    "            if self.clear_after.value:\n",
    "                time.sleep(3)\n",
    "                self.out.clear_output()\n",
    "\n",
    "    def display(self):\n",
    "        box = VBox([\n",
    "            self.repo_info,\n",
    "            HBox([self.org_name, self.repo_name]),\n",
    "            self.file_section,\n",
    "            HBox([self.file_type, self.sort_by]),\n",
    "            HBox([self.directory_label, self.directory_text, self.directory_update_btn]),\n",
    "            self.commit_section,\n",
    "            self.commit_msg,\n",
    "            self.upload_section,\n",
    "            HBox([self.create_pr, self.clear_after]),\n",
    "            self.update_btn,\n",
    "            self.ckpt_picker,\n",
    "            HBox([self.upload_btn, self.clear_btn, self.debug_toggle], layout=Layout(align_items='center')),\n",
    "             self.progress_text,\n",
    "            self.out,\n",
    "            self.debug_box,\n",
    "        ])\n",
    "        display(box)\n",
    "\n",
    "# Create and display the uploader - just one line to rule them all! ✨\n",
    "uploader = HuggingFaceUploader()\n",
    "uploader.display()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [
    "IZ_JYwvBLrg-",
    "PNF2kdyeO3Dn"
   ],
   "private_outputs": true,
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}