Files
skill-seekers-reference/tests/test_create_arguments.py
yusyus 83b03d9f9f fix: Resolve all linting errors from ruff
Fix 145 linting errors across CLI refactor code:

Type annotation modernization (Python 3.9+):
- Replace typing.Dict with dict
- Replace typing.List with list
- Replace typing.Set with set
- Replace Optional[X] with X | None

Code quality improvements:
- Remove trailing whitespace (W291)
- Remove whitespace from blank lines (W293)
- Remove unused imports (F401)
- Use dictionary lookup instead of if-elif chains (SIM116)
- Combine nested if statements (SIM102)

Files fixed (45 files):
- src/skill_seekers/cli/arguments/*.py (10 files)
- src/skill_seekers/cli/parsers/*.py (24 files)
- src/skill_seekers/cli/presets/*.py (4 files)
- src/skill_seekers/cli/create_command.py
- src/skill_seekers/cli/source_detector.py
- src/skill_seekers/cli/github_scraper.py
- tests/test_*.py (5 test files)

All files now pass ruff linting checks.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-15 20:20:55 +03:00

355 lines
13 KiB
Python

"""Tests for create command argument definitions.
Tests the three-tier argument system:
1. Universal arguments (work for all sources)
2. Source-specific arguments
3. Advanced arguments
"""
from skill_seekers.cli.arguments.create import (
UNIVERSAL_ARGUMENTS,
WEB_ARGUMENTS,
GITHUB_ARGUMENTS,
LOCAL_ARGUMENTS,
PDF_ARGUMENTS,
ADVANCED_ARGUMENTS,
get_universal_argument_names,
get_source_specific_arguments,
get_compatible_arguments,
add_create_arguments,
)
class TestUniversalArguments:
"""Test universal argument definitions."""
def test_universal_count(self):
"""Should have exactly 13 universal arguments (after Phase 1 consolidation)."""
assert len(UNIVERSAL_ARGUMENTS) == 13
def test_universal_argument_names(self):
"""Universal arguments should have expected names."""
expected_names = {
'name', 'description', 'output',
'enhance_level', 'api_key', # Phase 1: consolidated from enhance + enhance_local
'dry_run', 'verbose', 'quiet',
'chunk_for_rag', 'chunk_size', 'chunk_overlap', # Phase 2: RAG args from common.py
'preset', 'config'
}
assert set(UNIVERSAL_ARGUMENTS.keys()) == expected_names
def test_all_universal_have_flags(self):
"""All universal arguments should have flags."""
for arg_name, arg_def in UNIVERSAL_ARGUMENTS.items():
assert 'flags' in arg_def
assert len(arg_def['flags']) > 0
def test_all_universal_have_kwargs(self):
"""All universal arguments should have kwargs."""
for arg_name, arg_def in UNIVERSAL_ARGUMENTS.items():
assert 'kwargs' in arg_def
assert 'help' in arg_def['kwargs']
class TestSourceSpecificArguments:
"""Test source-specific argument definitions."""
def test_web_arguments_exist(self):
"""Web-specific arguments should be defined."""
assert len(WEB_ARGUMENTS) > 0
assert 'max_pages' in WEB_ARGUMENTS
assert 'rate_limit' in WEB_ARGUMENTS
assert 'workers' in WEB_ARGUMENTS
def test_github_arguments_exist(self):
"""GitHub-specific arguments should be defined."""
assert len(GITHUB_ARGUMENTS) > 0
assert 'repo' in GITHUB_ARGUMENTS
assert 'token' in GITHUB_ARGUMENTS
assert 'max_issues' in GITHUB_ARGUMENTS
def test_local_arguments_exist(self):
"""Local-specific arguments should be defined."""
assert len(LOCAL_ARGUMENTS) > 0
assert 'directory' in LOCAL_ARGUMENTS
assert 'languages' in LOCAL_ARGUMENTS
assert 'skip_patterns' in LOCAL_ARGUMENTS
def test_pdf_arguments_exist(self):
"""PDF-specific arguments should be defined."""
assert len(PDF_ARGUMENTS) > 0
assert 'pdf' in PDF_ARGUMENTS
assert 'ocr' in PDF_ARGUMENTS
def test_no_duplicate_flags_across_sources(self):
"""Source-specific arguments should not have duplicate flags."""
# Collect all flags from source-specific arguments
all_flags = set()
for source_args in [WEB_ARGUMENTS, GITHUB_ARGUMENTS, LOCAL_ARGUMENTS, PDF_ARGUMENTS]:
for arg_name, arg_def in source_args.items():
flags = arg_def['flags']
for flag in flags:
# Check if this flag already exists in source-specific args
if flag not in [f for arg in UNIVERSAL_ARGUMENTS.values() for f in arg['flags']]:
assert flag not in all_flags, f"Duplicate flag: {flag}"
all_flags.add(flag)
class TestAdvancedArguments:
"""Test advanced/rare argument definitions."""
def test_advanced_arguments_exist(self):
"""Advanced arguments should be defined."""
assert len(ADVANCED_ARGUMENTS) > 0
assert 'no_rate_limit' in ADVANCED_ARGUMENTS
assert 'interactive_enhancement' in ADVANCED_ARGUMENTS
class TestArgumentHelpers:
"""Test helper functions."""
def test_get_universal_argument_names(self):
"""Should return set of universal argument names."""
names = get_universal_argument_names()
assert isinstance(names, set)
assert len(names) == 13
assert 'name' in names
assert 'enhance_level' in names # Phase 1: consolidated flag
def test_get_source_specific_web(self):
"""Should return web-specific arguments."""
args = get_source_specific_arguments('web')
assert args == WEB_ARGUMENTS
def test_get_source_specific_github(self):
"""Should return github-specific arguments."""
args = get_source_specific_arguments('github')
assert args == GITHUB_ARGUMENTS
def test_get_source_specific_local(self):
"""Should return local-specific arguments."""
args = get_source_specific_arguments('local')
assert args == LOCAL_ARGUMENTS
def test_get_source_specific_pdf(self):
"""Should return pdf-specific arguments."""
args = get_source_specific_arguments('pdf')
assert args == PDF_ARGUMENTS
def test_get_source_specific_config(self):
"""Config should return empty dict (no extra args)."""
args = get_source_specific_arguments('config')
assert args == {}
def test_get_source_specific_unknown(self):
"""Unknown source should return empty dict."""
args = get_source_specific_arguments('unknown')
assert args == {}
class TestCompatibleArguments:
"""Test compatible argument detection."""
def test_web_compatible_arguments(self):
"""Web source should include universal + web + advanced."""
compatible = get_compatible_arguments('web')
# Should include universal arguments
assert 'name' in compatible
assert 'enhance_level' in compatible # Phase 1: consolidated flag
# Should include web-specific arguments
assert 'max_pages' in compatible
assert 'rate_limit' in compatible
# Should include advanced arguments
assert 'no_rate_limit' in compatible
def test_github_compatible_arguments(self):
"""GitHub source should include universal + github + advanced."""
compatible = get_compatible_arguments('github')
# Should include universal arguments
assert 'name' in compatible
# Should include github-specific arguments
assert 'repo' in compatible
assert 'token' in compatible
# Should include advanced arguments
assert 'interactive_enhancement' in compatible
def test_local_compatible_arguments(self):
"""Local source should include universal + local + advanced."""
compatible = get_compatible_arguments('local')
# Should include universal arguments
assert 'description' in compatible
# Should include local-specific arguments
assert 'directory' in compatible
assert 'languages' in compatible
def test_pdf_compatible_arguments(self):
"""PDF source should include universal + pdf + advanced."""
compatible = get_compatible_arguments('pdf')
# Should include universal arguments
assert 'output' in compatible
# Should include pdf-specific arguments
assert 'pdf' in compatible
assert 'ocr' in compatible
def test_config_compatible_arguments(self):
"""Config source should include universal + advanced only."""
compatible = get_compatible_arguments('config')
# Should include universal arguments
assert 'config' in compatible
# Should include advanced arguments
assert 'no_preserve_code_blocks' in compatible
# Should not include source-specific arguments
assert 'repo' not in compatible
assert 'directory' not in compatible
class TestAddCreateArguments:
"""Test add_create_arguments function."""
def test_default_mode_adds_universal_only(self):
"""Default mode should add only universal arguments + source positional."""
import argparse
parser = argparse.ArgumentParser()
add_create_arguments(parser, mode='default')
# Parse to get all arguments
args = vars(parser.parse_args([]))
# Should have universal arguments
assert 'name' in args
assert 'enhance_level' in args
assert 'chunk_for_rag' in args
# Should not have source-specific arguments (they're not added in default mode)
# Note: argparse won't error on unknown args, but they won't be in namespace
def test_web_mode_adds_web_arguments(self):
"""Web mode should add universal + web arguments."""
import argparse
parser = argparse.ArgumentParser()
add_create_arguments(parser, mode='web')
args = vars(parser.parse_args([]))
# Should have universal arguments
assert 'name' in args
# Should have web-specific arguments
assert 'max_pages' in args
assert 'rate_limit' in args
def test_all_mode_adds_all_arguments(self):
"""All mode should add every argument."""
import argparse
parser = argparse.ArgumentParser()
add_create_arguments(parser, mode='all')
args = vars(parser.parse_args([]))
# Should have universal arguments
assert 'name' in args
# Should have all source-specific arguments
assert 'max_pages' in args # web
assert 'repo' in args # github
assert 'directory' in args # local
assert 'pdf' in args # pdf
# Should have advanced arguments
assert 'no_rate_limit' in args
def test_positional_source_argument_always_added(self):
"""Source positional argument should always be added."""
import argparse
for mode in ['default', 'web', 'github', 'local', 'pdf', 'all']:
parser = argparse.ArgumentParser()
add_create_arguments(parser, mode=mode)
# Should accept source as positional
args = parser.parse_args(['some_source'])
assert args.source == 'some_source'
class TestNoDuplicates:
"""Test that there are no duplicate arguments across tiers."""
def test_no_duplicates_between_universal_and_web(self):
"""Universal and web args should not overlap."""
universal_flags = {
flag for arg in UNIVERSAL_ARGUMENTS.values()
for flag in arg['flags']
}
web_flags = {
flag for arg in WEB_ARGUMENTS.values()
for flag in arg['flags']
}
# Allow some overlap since we intentionally include common args
# in multiple places, but check that they're properly defined
overlap = universal_flags & web_flags
# There should be minimal overlap (only if intentional)
assert len(overlap) == 0, f"Unexpected overlap: {overlap}"
def test_no_duplicates_between_source_specific_args(self):
"""Different source-specific arg groups should not overlap."""
web_flags = {flag for arg in WEB_ARGUMENTS.values() for flag in arg['flags']}
github_flags = {flag for arg in GITHUB_ARGUMENTS.values() for flag in arg['flags']}
local_flags = {flag for arg in LOCAL_ARGUMENTS.values() for flag in arg['flags']}
pdf_flags = {flag for arg in PDF_ARGUMENTS.values() for flag in arg['flags']}
# No overlap between different source types
assert len(web_flags & github_flags) == 0
assert len(web_flags & local_flags) == 0
assert len(web_flags & pdf_flags) == 0
assert len(github_flags & local_flags) == 0
assert len(github_flags & pdf_flags) == 0
assert len(local_flags & pdf_flags) == 0
class TestArgumentQuality:
"""Test argument definition quality."""
def test_all_arguments_have_help_text(self):
"""Every argument should have help text."""
all_args = {
**UNIVERSAL_ARGUMENTS,
**WEB_ARGUMENTS,
**GITHUB_ARGUMENTS,
**LOCAL_ARGUMENTS,
**PDF_ARGUMENTS,
**ADVANCED_ARGUMENTS,
}
for arg_name, arg_def in all_args.items():
assert 'help' in arg_def['kwargs'], f"{arg_name} missing help text"
assert len(arg_def['kwargs']['help']) > 0, f"{arg_name} has empty help text"
def test_boolean_arguments_use_store_true(self):
"""Boolean flags should use store_true action."""
all_args = {
**UNIVERSAL_ARGUMENTS,
**WEB_ARGUMENTS,
**GITHUB_ARGUMENTS,
**LOCAL_ARGUMENTS,
**PDF_ARGUMENTS,
**ADVANCED_ARGUMENTS,
}
boolean_args = [
'dry_run', 'verbose', 'quiet',
'chunk_for_rag', 'skip_scrape', 'resume', 'fresh', 'async_mode',
'no_issues', 'no_changelog', 'no_releases', 'scrape_only',
'skip_patterns', 'skip_test_examples', 'ocr', 'no_rate_limit'
]
for arg_name in boolean_args:
if arg_name in all_args:
action = all_args[arg_name]['kwargs'].get('action')
assert action == 'store_true', f"{arg_name} should use store_true"