Repository: huggingface/huggingface_hub
Pull request #1022 (2022-08-31 09:29:42)

enable http request retry under proxy
Fix the issue that when proxy is used, connection timeout raise "ProxyError" rather than "ConnectTimeout".
https://github.com/huggingface/huggingface_hub/issues/1020

HuggingFaceDocBuilderDev: The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/huggingface_hub/pr_1022). All of your documentation changes will be reflected on that endpoint.

Patch:
diff --git a/src/huggingface_hub/file_download.py b/src/huggingface_hub/file_download.py
index 929c638e..f6eaf0f8 100644
--- a/src/huggingface_hub/file_download.py
+++ b/src/huggingface_hub/file_download.py
@@ -219,6 +219,8 @@ def hf_hub_url(
 
     -  [1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
     """
+    if subfolder == "":
+        subfolder = None
     if subfolder is not None:
         filename = f"{subfolder}/{filename}"
 
@@ -461,7 +463,10 @@ def _request_wrapper(
                 method=method.upper(), url=url, timeout=timeout, **params
             )
             success = True
-        except requests.exceptions.ConnectTimeout as err:
+        except (
+            requests.exceptions.ConnectTimeout,
+            requests.exceptions.ProxyError,
+        ) as err:
             if tries > max_retries:
                 raise err
             else:
@@ -1032,6 +1037,8 @@ def hf_hub_download(
     if isinstance(cache_dir, Path):
         cache_dir = str(cache_dir)
 
+    if subfolder == "":
+        subfolder = None
     if subfolder is not None:
         # This is used to create a URL, and not a local path, hence the forward slash.
         filename = f"{subfolder}/{filename}"


Test patch:
diff --git a/tests/test_file_download.py b/tests/test_file_download.py
index 2abd0f7b..50b3d4ca 100644
--- a/tests/test_file_download.py
+++ b/tests/test_file_download.py
@@ -13,6 +13,7 @@
 # limitations under the License.
 import os
 import unittest
+from pathlib import Path
 from tempfile import TemporaryDirectory
 
 import pytest
@@ -247,6 +248,46 @@ class CachedDownloadTests(unittest.TestCase):
                 )
                 self.assertTrue(os.path.exists(filepath))
 
+    def test_hf_hub_download_with_empty_subfolder(self):
+        """
+        Check subfolder arg is processed correctly when empty string is passed to
+        `hf_hub_download`.
+
+        See https://github.com/huggingface/huggingface_hub/issues/1016.
+        """
+        filepath = Path(
+            hf_hub_download(
+                DUMMY_MODEL_ID,
+                filename=CONFIG_NAME,
+                subfolder="",  # Subfolder should be processed as `None`
+            )
+        )
+
+        # Check file exists and is not in a subfolder in cache
+        # e.g: "(...)/snapshots/<commit-id>/config.json"
+        self.assertTrue(filepath.is_file())
+        self.assertEqual(filepath.name, CONFIG_NAME)
+        self.assertEqual(Path(filepath).parent.parent.name, "snapshots")
+
+    def test_hf_hub_url_with_empty_subfolder(self):
+        """
+        Check subfolder arg is processed correctly when empty string is passed to
+        `hf_hub_url`.
+
+        See https://github.com/huggingface/huggingface_hub/issues/1016.
+        """
+        url = hf_hub_url(
+            DUMMY_MODEL_ID,
+            filename=CONFIG_NAME,
+            subfolder="",  # Subfolder should be processed as `None`
+        )
+        self.assertTrue(
+            url.endswith(
+                # "./resolve/main/config.json" and not "./resolve/main//config.json"
+                f"{DUMMY_MODEL_ID}/resolve/main/config.json",
+            )
+        )
+
     def test_hf_hub_download_legacy(self):
         filepath = hf_hub_download(
             DUMMY_MODEL_ID,