CLI Implementation with Click (#2107)
* Initial CLI implementation with click package * Adding fetch command for pulling examples and deepspeed configs * Automating default options for CliArgs classes * Mimicking existing no config behavior * bugfix in choose_config * Updating fetch to sync instead of re-download * bugfix * isort fix * fixing yaml isort order * pre-commit fixes * simplifying argument parsing -- pass through kwargs to do_cli * make accelerate launch default for non-preprocess commands * fixing arg handling * testing None placeholder approach * removing hacky --use-gpu argument to preprocess command * Adding brief README documentation for CLI * remove (New) * Initial CLI pytest tests * progress on CLI pytest * adding inference CLI tests; cleanup * Refactor train CLI tests to remove various mocking * Major CLI test refator; adding remaining CLI codepath test coverage * pytest fixes * remove integration markers * parallelizing examples, deepspeed config downloads; rename test to match other CLI test naming * moving cli pytest due to isolation issues; cleanup * testing fixes; various minor improvements * fix * tests fix * Update tests/cli/conftest.py Co-authored-by: Wing Lian <wing.lian@gmail.com> --------- Co-authored-by: Dan Saunders <dan@axolotl.ai> Co-authored-by: Wing Lian <wing.lian@gmail.com>
This commit is contained in:
89
tests/cli/test_utils.py
Normal file
89
tests/cli/test_utils.py
Normal file
@@ -0,0 +1,89 @@
|
||||
"""pytest tests for axolotl CLI utils."""
|
||||
# pylint: disable=redefined-outer-name
|
||||
import json
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import click
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from axolotl.cli.utils import fetch_from_github
|
||||
|
||||
# Sample GitHub API response
|
||||
MOCK_TREE_RESPONSE = {
|
||||
"tree": [
|
||||
{"path": "examples/config1.yml", "type": "blob", "sha": "abc123"},
|
||||
{"path": "examples/config2.yml", "type": "blob", "sha": "def456"},
|
||||
{"path": "other/file.txt", "type": "blob", "sha": "xyz789"},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_responses():
|
||||
"""Mock responses for API and file downloads"""
|
||||
|
||||
def mock_get(url, timeout=None): # pylint: disable=unused-argument
|
||||
response = Mock()
|
||||
if "api.github.com" in url:
|
||||
response.text = json.dumps(MOCK_TREE_RESPONSE)
|
||||
else:
|
||||
response.content = b"file content"
|
||||
return response
|
||||
|
||||
return mock_get
|
||||
|
||||
|
||||
def test_fetch_from_github_new_files(tmp_path, mock_responses):
|
||||
"""Test fetching new files"""
|
||||
with patch("requests.get", mock_responses):
|
||||
fetch_from_github("examples/", tmp_path)
|
||||
|
||||
# Verify files were created
|
||||
assert (tmp_path / "config1.yml").exists()
|
||||
assert (tmp_path / "config2.yml").exists()
|
||||
assert not (tmp_path / "file.txt").exists()
|
||||
|
||||
|
||||
def test_fetch_from_github_unchanged_files(tmp_path, mock_responses):
|
||||
"""Test handling of unchanged files"""
|
||||
# Create existing file with matching SHA
|
||||
existing_file = tmp_path / "config1.yml"
|
||||
existing_file.write_bytes(b"file content")
|
||||
|
||||
with patch("requests.get", mock_responses):
|
||||
fetch_from_github("examples/", tmp_path)
|
||||
|
||||
# File should not be downloaded again
|
||||
assert existing_file.read_bytes() == b"file content"
|
||||
|
||||
|
||||
def test_fetch_from_github_invalid_prefix(mock_responses):
|
||||
"""Test error handling for invalid directory prefix"""
|
||||
with patch("requests.get", mock_responses):
|
||||
with pytest.raises(click.ClickException):
|
||||
fetch_from_github("nonexistent/", None)
|
||||
|
||||
|
||||
def test_fetch_from_github_network_error():
|
||||
"""Test handling of network errors"""
|
||||
with patch("requests.get", side_effect=requests.RequestException):
|
||||
with pytest.raises(requests.RequestException):
|
||||
fetch_from_github("examples/", None)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def integration_test_dir(tmp_path):
|
||||
"""Fixture for integration test directory that cleans up after itself"""
|
||||
test_dir = tmp_path / "github_downloads"
|
||||
test_dir.mkdir(parents=True)
|
||||
yield test_dir
|
||||
|
||||
|
||||
def test_fetch_from_github_real(integration_test_dir):
|
||||
"""Test actual GitHub API interaction"""
|
||||
fetch_from_github("examples/", integration_test_dir)
|
||||
|
||||
# Verify some known files exist
|
||||
assert (integration_test_dir / "openllama-3b" / "lora.yml").exists()
|
||||
assert (integration_test_dir / "openllama-3b" / "qlora.yml").exists()
|
||||
Reference in New Issue
Block a user