Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions tests/test_loader_glob_skip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
"""Tests that HfFileSystem().glob() is skipped when is_model or is_peft is False.

The glob calls in FastLanguageModel.from_pretrained and FastModel.from_pretrained
exist solely to detect repos with both config.json and adapter_config.json. When
either AutoConfig or PeftConfig fails to load, the glob cannot find both files,
so calling it is redundant and risks hanging on slow networks.
"""

import os
import unittest
from unittest.mock import MagicMock, patch


class TestGlobSkippedWhenNotBothConfigs(unittest.TestCase):
"""Verify HfFileSystem.glob is not called when is_model or is_peft is False."""

def _run_both_exist_block(
self, is_model, is_peft, supports_llama32, model_name, is_local_dir = False
):
"""Simulate the both_exist detection block from loader.py.

This mirrors the exact logic at lines 500-517 / 1276-1292 of loader.py.
Returns (both_exist, glob_called).
"""
from unittest.mock import MagicMock

both_exist = (is_model and is_peft) and not supports_llama32
glob_mock = MagicMock(
return_value = [
f"{model_name}/config.json",
f"{model_name}/adapter_config.json",
]
)

# This mirrors the guarded block in loader.py
if supports_llama32 and is_model and is_peft:
if is_local_dir:
# Local path branch — would use os.path.exists in real code
both_exist = True # simulate both files present locally
else:
files = glob_mock(f"{model_name}/*.json")
files = list(os.path.split(x)[-1] for x in files)
if (
sum(x == "adapter_config.json" or x == "config.json" for x in files)
>= 2
):
both_exist = True

return both_exist, glob_mock.called
Comment on lines +17 to +49

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The _run_both_exist_block helper re-implements the logic from loader.py instead of testing the actual code. This creates a "tautological test" where you are testing your own simulation of the logic rather than the actual implementation in unsloth/models/loader.py. If the real code diverges from this simulation, the tests will still pass while the bug remains. It is recommended to test the actual FastLanguageModel.from_pretrained method by mocking its external dependencies (like HfFileSystem and AutoConfig).


# --- Cases where glob should NOT be called ---

def test_glob_skipped_when_is_model_false(self):
both_exist, glob_called = self._run_both_exist_block(
is_model = False,
is_peft = True,
supports_llama32 = True,
model_name = "org/some-adapter",
)
self.assertFalse(glob_called, "glob should not be called when is_model=False")
self.assertFalse(both_exist)

def test_glob_skipped_when_is_peft_false(self):
both_exist, glob_called = self._run_both_exist_block(
is_model = True,
is_peft = False,
supports_llama32 = True,
model_name = "org/some-model",
)
self.assertFalse(glob_called, "glob should not be called when is_peft=False")
self.assertFalse(both_exist)

def test_glob_skipped_when_both_false(self):
both_exist, glob_called = self._run_both_exist_block(
is_model = False,
is_peft = False,
supports_llama32 = True,
model_name = "org/bad-repo",
)
self.assertFalse(glob_called, "glob should not be called when both are False")
self.assertFalse(both_exist)

def test_glob_skipped_when_supports_llama32_false(self):
both_exist, glob_called = self._run_both_exist_block(
is_model = True,
is_peft = True,
supports_llama32 = False,
model_name = "org/some-model",
)
self.assertFalse(
glob_called, "glob should not be called when SUPPORTS_LLAMA32=False"
)
# both_exist is set by the old-style check: (is_model and is_peft) and not SUPPORTS_LLAMA32
self.assertTrue(both_exist)

# --- Cases where glob SHOULD be called ---

def test_glob_called_when_both_true_and_supports_llama32(self):
both_exist, glob_called = self._run_both_exist_block(
is_model = True,
is_peft = True,
supports_llama32 = True,
model_name = "org/mixed-repo",
)
self.assertTrue(
glob_called, "glob should be called when is_model and is_peft are both True"
)
self.assertTrue(both_exist)

def test_local_dir_skips_glob(self):
both_exist, glob_called = self._run_both_exist_block(
is_model = True,
is_peft = True,
supports_llama32 = True,
model_name = "/local/path/to/model",
is_local_dir = True,
)
self.assertFalse(glob_called, "glob should not be called for local directories")
self.assertTrue(both_exist)


class TestLoaderSourceHasGuard(unittest.TestCase):
"""Verify the actual loader.py source code has the is_model/is_peft guard."""

def test_loader_source_has_guard(self):
"""Check that both SUPPORTS_LLAMA32 checks in loader.py include is_model and is_peft."""
loader_path = os.path.join(
os.path.dirname(__file__), os.pardir, "unsloth", "models", "loader.py"
)
with open(loader_path) as f:
source = f.read()

# Find all lines with the SUPPORTS_LLAMA32 check near glob usage
lines = source.splitlines()
guard_lines = [
line.strip()
for line in lines
if "SUPPORTS_LLAMA32" in line and "if " in line and "is_model" in line

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Checking the source code via string matching is brittle and the current filter is incomplete as it only checks for is_model. A more robust approach would be to use the ast module to parse the source, or preferably, rely on functional tests that verify the behavior by mocking HfFileSystem.

Suggested change
if "SUPPORTS_LLAMA32" in line and "if " in line and "is_model" in line
if all(x in line for x in ["if ", "SUPPORTS_LLAMA32", "is_model", "is_peft"])

]
# There should be exactly 2 guarded checks (one per from_pretrained method)
self.assertEqual(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This assertion will fail because the current version of unsloth/models/loader.py (as seen in lines 511 and 1285) does not yet include the is_model and is_peft variables in the if SUPPORTS_LLAMA32: guard. Since this PR only adds the tests without the corresponding implementation changes in the loader, the test suite will break in CI. You should include the loader changes in this PR or ensure they are merged simultaneously.

len(guard_lines),
2,
f"Expected 2 guarded SUPPORTS_LLAMA32 checks with is_model/is_peft, found {len(guard_lines)}: {guard_lines}",
Comment on lines +141 to +144

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Drop hard-coded guarded-line count assertion

This assertion requires loader.py to contain exactly two SUPPORTS_LLAMA32 condition lines that already include is_model/is_peft, but the parent branch (6100867) still has both checks as plain if SUPPORTS_LLAMA32:. As a result, guard_lines is always empty and this new test fails consistently (pytest tests/test_loader_glob_skip.py), making the commit non-mergeable unless the loader guard implementation lands in the same change.

Useful? React with 👍 / 👎.

)
for line in guard_lines:
self.assertIn("is_model", line)
self.assertIn("is_peft", line)


if __name__ == "__main__":
unittest.main()
Loading