Skip to content

Commit a258320

Browse files
Wauplinclaude
andcommitted
Fix compat with filelock < 3.10.0 by conditionally using mode= parameter
The `mode=` parameter was added in filelock 3.10.0. When an older version is installed, skip the parameter and emit a warning suggesting to upgrade. Fixes #3777 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1346ac6 commit a258320

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

src/huggingface_hub/utils/_fixes.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44
import stat
55
import tempfile
66
import time
7+
import warnings
78
from functools import partial
89
from pathlib import Path
910
from typing import Callable, Generator, Optional, Union
1011

1112
import yaml
1213
from filelock import BaseFileLock, FileLock, SoftFileLock, Timeout
14+
from packaging import version as packaging_version
1315

1416
from .. import constants
1517
from . import logging
18+
from ._runtime import get_filelock_version
1619

1720

1821
logger = logging.get_logger(__name__)
@@ -73,6 +76,32 @@ def _set_write_permission_and_retry(func, path, excinfo):
7376
func(path)
7477

7578

79+
# `mode=` parameter was added in filelock 3.10.0. We use it to create group-writable lock files (0o664).
80+
# If filelock is too old, we skip the `mode=` parameter and warn the user.
81+
_FILELOCK_SUPPORTS_MODE = packaging_version.parse(get_filelock_version()) >= packaging_version.parse("3.10.0")
82+
_FILELOCK_MODE_WARNING_EMITTED = False
83+
84+
85+
def _create_filelock(lock_cls: type, lock_file: Union[str, Path], **kwargs) -> BaseFileLock:
86+
"""Create a filelock instance, passing `mode=0o664` if supported by the installed filelock version."""
87+
global _FILELOCK_MODE_WARNING_EMITTED
88+
if _FILELOCK_SUPPORTS_MODE:
89+
return lock_cls(lock_file, mode=0o664, **kwargs)
90+
else:
91+
if not _FILELOCK_MODE_WARNING_EMITTED:
92+
warnings.warn(
93+
f"filelock version {get_filelock_version()} does not support the `mode=` parameter. "
94+
"Lock files will be created with the default mode. "
95+
"Consider upgrading filelock to 3.10.0+ (`pip install -U filelock`) if you encounter "
96+
"lock permission issues in a multi-user environment. "
97+
"See https://github.com/huggingface/huggingface_hub/issues/3714 for more details.",
98+
UserWarning,
99+
stacklevel=3,
100+
)
101+
_FILELOCK_MODE_WARNING_EMITTED = True
102+
return lock_cls(lock_file, **kwargs)
103+
104+
76105
@contextlib.contextmanager
77106
def WeakFileLock(
78107
lock_file: Union[str, Path], *, timeout: Optional[float] = None
@@ -89,7 +118,7 @@ def WeakFileLock(
89118
If a timeout is provided, a `filelock.Timeout` exception is raised if the lock is not acquired within the timeout.
90119
"""
91120
log_interval = constants.FILELOCK_LOG_EVERY_SECONDS
92-
lock = FileLock(lock_file, timeout=log_interval, mode=0o664)
121+
lock = _create_filelock(FileLock, lock_file, timeout=log_interval)
93122
start_time = time.time()
94123

95124
while True:
@@ -108,7 +137,7 @@ def WeakFileLock(
108137
logger.warning(
109138
"FileSystem does not appear to support flock. Falling back to SoftFileLock for %s", lock_file
110139
)
111-
lock = SoftFileLock(lock_file, timeout=log_interval)
140+
lock = _create_filelock(SoftFileLock, lock_file, timeout=log_interval)
112141
continue
113142
else:
114143
break

src/huggingface_hub/utils/_runtime.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"fastai": {"fastai"},
3535
"fastapi": {"fastapi"},
3636
"fastcore": {"fastcore"},
37+
"filelock": {"filelock"},
3738
"gradio": {"gradio"},
3839
"graphviz": {"graphviz"},
3940
"hf_xet": {"hf_xet"},
@@ -126,6 +127,11 @@ def get_fastcore_version() -> str:
126127
return _get_version("fastcore")
127128

128129

130+
# Filelock
131+
def get_filelock_version() -> str:
132+
return _get_version("filelock")
133+
134+
129135
# FastAI
130136
def is_gradio_available() -> bool:
131137
return is_package_available("gradio")

0 commit comments

Comments
 (0)