From 83b03d9f9f8c10c04457b7fffcc2034e3a93e297 Mon Sep 17 00:00:00 2001 From: yusyus Date: Sun, 15 Feb 2026 20:20:55 +0300 Subject: [PATCH] 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 --- src/skill_seekers/cli/arguments/analyze.py | 7 +- src/skill_seekers/cli/arguments/common.py | 25 +++--- src/skill_seekers/cli/arguments/create.py | 47 +++++------ src/skill_seekers/cli/arguments/enhance.py | 6 +- src/skill_seekers/cli/arguments/github.py | 18 ++--- src/skill_seekers/cli/arguments/package.py | 6 +- src/skill_seekers/cli/arguments/pdf.py | 6 +- src/skill_seekers/cli/arguments/scrape.py | 18 ++--- src/skill_seekers/cli/arguments/unified.py | 6 +- src/skill_seekers/cli/arguments/upload.py | 6 +- src/skill_seekers/cli/create_command.py | 8 +- src/skill_seekers/cli/github_scraper.py | 14 +--- src/skill_seekers/cli/parsers/__init__.py | 4 - .../cli/parsers/analyze_parser.py | 5 +- src/skill_seekers/cli/parsers/base.py | 1 - .../cli/parsers/config_parser.py | 1 - .../cli/parsers/create_parser.py | 1 - .../cli/parsers/enhance_parser.py | 3 +- .../cli/parsers/enhance_status_parser.py | 1 - .../cli/parsers/estimate_parser.py | 1 - .../cli/parsers/github_parser.py | 3 +- .../cli/parsers/install_agent_parser.py | 1 - .../cli/parsers/install_parser.py | 1 - .../cli/parsers/multilang_parser.py | 1 - .../cli/parsers/package_parser.py | 3 +- src/skill_seekers/cli/parsers/pdf_parser.py | 3 +- .../cli/parsers/quality_parser.py | 1 - .../cli/parsers/resume_parser.py | 1 - .../cli/parsers/scrape_parser.py | 3 +- .../cli/parsers/stream_parser.py | 1 - .../cli/parsers/test_examples_parser.py | 1 - .../cli/parsers/unified_parser.py | 3 +- .../cli/parsers/update_parser.py | 1 - .../cli/parsers/upload_parser.py | 3 +- src/skill_seekers/cli/presets/__init__.py | 1 - .../cli/presets/analyze_presets.py | 80 +++++++++---------- .../cli/presets/github_presets.py | 28 +++---- src/skill_seekers/cli/presets/manager.py | 4 - .../cli/presets/scrape_presets.py | 35 ++++---- src/skill_seekers/cli/source_detector.py | 8 +- tests/test_cli_refactor_e2e.py | 9 --- tests/test_create_arguments.py | 9 --- tests/test_create_integration_basic.py | 5 -- tests/test_parser_sync.py | 4 - tests/test_source_detector.py | 11 --- 45 files changed, 134 insertions(+), 270 deletions(-) diff --git a/src/skill_seekers/cli/arguments/analyze.py b/src/skill_seekers/cli/arguments/analyze.py index 06930cf..9eab0de 100644 --- a/src/skill_seekers/cli/arguments/analyze.py +++ b/src/skill_seekers/cli/arguments/analyze.py @@ -8,10 +8,9 @@ Includes preset system support for #268. """ import argparse -from typing import Dict, Any +from typing import Any - -ANALYZE_ARGUMENTS: Dict[str, Dict[str, Any]] = { +ANALYZE_ARGUMENTS: dict[str, dict[str, Any]] = { # Core options "directory": { "flags": ("--directory",), @@ -172,7 +171,6 @@ ANALYZE_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_analyze_arguments(parser: argparse.ArgumentParser) -> None: """Add all analyze command arguments to a parser.""" for arg_name, arg_def in ANALYZE_ARGUMENTS.items(): @@ -180,7 +178,6 @@ def add_analyze_arguments(parser: argparse.ArgumentParser) -> None: kwargs = arg_def["kwargs"] parser.add_argument(*flags, **kwargs) - def get_analyze_argument_names() -> set: """Get the set of analyze argument destination names.""" return set(ANALYZE_ARGUMENTS.keys()) diff --git a/src/skill_seekers/cli/arguments/common.py b/src/skill_seekers/cli/arguments/common.py index 177f7a8..a580d69 100644 --- a/src/skill_seekers/cli/arguments/common.py +++ b/src/skill_seekers/cli/arguments/common.py @@ -5,12 +5,11 @@ and provide consistent behavior for configuration, output control, and help. """ import argparse -from typing import Dict, Any - +from typing import Any # Common argument definitions as data structure # These are arguments that appear in MULTIPLE commands -COMMON_ARGUMENTS: Dict[str, Dict[str, Any]] = { +COMMON_ARGUMENTS: dict[str, dict[str, Any]] = { "config": { "flags": ("--config", "-c"), "kwargs": { @@ -67,10 +66,9 @@ COMMON_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - # RAG (Retrieval-Augmented Generation) arguments # These are shared across commands that support RAG chunking -RAG_ARGUMENTS: Dict[str, Dict[str, Any]] = { +RAG_ARGUMENTS: dict[str, dict[str, Any]] = { "chunk_for_rag": { "flags": ("--chunk-for-rag",), "kwargs": { @@ -98,15 +96,14 @@ RAG_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_common_arguments(parser: argparse.ArgumentParser) -> None: """Add common arguments to a parser. - + These arguments are shared across most commands for consistent UX. - + Args: parser: The ArgumentParser to add arguments to - + Example: >>> parser = argparse.ArgumentParser() >>> add_common_arguments(parser) @@ -117,7 +114,6 @@ def add_common_arguments(parser: argparse.ArgumentParser) -> None: kwargs = arg_def["kwargs"] parser.add_argument(*flags, **kwargs) - def get_common_argument_names() -> set: """Get the set of common argument destination names. @@ -126,7 +122,6 @@ def get_common_argument_names() -> set: """ return set(COMMON_ARGUMENTS.keys()) - def add_rag_arguments(parser: argparse.ArgumentParser) -> None: """Add RAG (Retrieval-Augmented Generation) arguments to a parser. @@ -145,7 +140,6 @@ def add_rag_arguments(parser: argparse.ArgumentParser) -> None: kwargs = arg_def["kwargs"] parser.add_argument(*flags, **kwargs) - def get_rag_argument_names() -> set: """Get the set of RAG argument destination names. @@ -154,16 +148,15 @@ def get_rag_argument_names() -> set: """ return set(RAG_ARGUMENTS.keys()) - def get_argument_help(arg_name: str) -> str: """Get the help text for a common argument. - + Args: arg_name: Name of the argument (e.g., 'config') - + Returns: Help text string - + Raises: KeyError: If argument doesn't exist """ diff --git a/src/skill_seekers/cli/arguments/create.py b/src/skill_seekers/cli/arguments/create.py index 18ea0ee..9729a27 100644 --- a/src/skill_seekers/cli/arguments/create.py +++ b/src/skill_seekers/cli/arguments/create.py @@ -10,18 +10,17 @@ This enables progressive disclosure in help text while maintaining """ import argparse -from typing import Dict, Any, Set, List +from typing import Any from skill_seekers.cli.constants import DEFAULT_RATE_LIMIT from .common import RAG_ARGUMENTS - # ============================================================================= # TIER 1: UNIVERSAL ARGUMENTS (15 flags) # ============================================================================= # These arguments work for ALL source types -UNIVERSAL_ARGUMENTS: Dict[str, Dict[str, Any]] = { +UNIVERSAL_ARGUMENTS: dict[str, dict[str, Any]] = { # Identity arguments "name": { "flags": ("--name",), @@ -118,13 +117,12 @@ UNIVERSAL_ARGUMENTS: Dict[str, Dict[str, Any]] = { # Merge RAG arguments from common.py into universal arguments UNIVERSAL_ARGUMENTS.update(RAG_ARGUMENTS) - # ============================================================================= # TIER 2: SOURCE-SPECIFIC ARGUMENTS # ============================================================================= # Web scraping specific (from scrape.py) -WEB_ARGUMENTS: Dict[str, Dict[str, Any]] = { +WEB_ARGUMENTS: dict[str, dict[str, Any]] = { "url": { "flags": ("--url",), "kwargs": { @@ -189,7 +187,7 @@ WEB_ARGUMENTS: Dict[str, Dict[str, Any]] = { } # GitHub repository specific (from github.py) -GITHUB_ARGUMENTS: Dict[str, Dict[str, Any]] = { +GITHUB_ARGUMENTS: dict[str, dict[str, Any]] = { "repo": { "flags": ("--repo",), "kwargs": { @@ -261,7 +259,7 @@ GITHUB_ARGUMENTS: Dict[str, Dict[str, Any]] = { } # Local codebase specific (from analyze.py) -LOCAL_ARGUMENTS: Dict[str, Dict[str, Any]] = { +LOCAL_ARGUMENTS: dict[str, dict[str, Any]] = { "directory": { "flags": ("--directory",), "kwargs": { @@ -324,7 +322,7 @@ LOCAL_ARGUMENTS: Dict[str, Dict[str, Any]] = { } # PDF specific (from pdf.py) -PDF_ARGUMENTS: Dict[str, Dict[str, Any]] = { +PDF_ARGUMENTS: dict[str, dict[str, Any]] = { "pdf": { "flags": ("--pdf",), "kwargs": { @@ -350,13 +348,12 @@ PDF_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - # ============================================================================= # TIER 3: ADVANCED/RARE ARGUMENTS # ============================================================================= # Hidden from default help, shown only with --help-advanced -ADVANCED_ARGUMENTS: Dict[str, Dict[str, Any]] = { +ADVANCED_ARGUMENTS: dict[str, dict[str, Any]] = { "no_rate_limit": { "flags": ("--no-rate-limit",), "kwargs": { @@ -387,17 +384,15 @@ ADVANCED_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - # ============================================================================= # HELPER FUNCTIONS # ============================================================================= -def get_universal_argument_names() -> Set[str]: +def get_universal_argument_names() -> set[str]: """Get set of universal argument names.""" return set(UNIVERSAL_ARGUMENTS.keys()) - -def get_source_specific_arguments(source_type: str) -> Dict[str, Dict[str, Any]]: +def get_source_specific_arguments(source_type: str) -> dict[str, dict[str, Any]]: """Get source-specific arguments for a given source type. Args: @@ -406,21 +401,16 @@ def get_source_specific_arguments(source_type: str) -> Dict[str, Dict[str, Any]] Returns: Dict of argument definitions """ - if source_type == 'web': - return WEB_ARGUMENTS - elif source_type == 'github': - return GITHUB_ARGUMENTS - elif source_type == 'local': - return LOCAL_ARGUMENTS - elif source_type == 'pdf': - return PDF_ARGUMENTS - elif source_type == 'config': - return {} # Config files don't have extra args - else: - return {} + source_args = { + 'web': WEB_ARGUMENTS, + 'github': GITHUB_ARGUMENTS, + 'local': LOCAL_ARGUMENTS, + 'pdf': PDF_ARGUMENTS, + 'config': {}, # Config files don't have extra args + } + return source_args.get(source_type, {}) - -def get_compatible_arguments(source_type: str) -> List[str]: +def get_compatible_arguments(source_type: str) -> list[str]: """Get list of compatible argument names for a source type. Args: @@ -441,7 +431,6 @@ def get_compatible_arguments(source_type: str) -> List[str]: return compatible - def add_create_arguments(parser: argparse.ArgumentParser, mode: str = 'default') -> None: """Add create command arguments to parser. diff --git a/src/skill_seekers/cli/arguments/enhance.py b/src/skill_seekers/cli/arguments/enhance.py index c1b5cb0..753c8ca 100644 --- a/src/skill_seekers/cli/arguments/enhance.py +++ b/src/skill_seekers/cli/arguments/enhance.py @@ -6,10 +6,9 @@ import and use these definitions. """ import argparse -from typing import Dict, Any +from typing import Any - -ENHANCE_ARGUMENTS: Dict[str, Dict[str, Any]] = { +ENHANCE_ARGUMENTS: dict[str, dict[str, Any]] = { # Positional argument "skill_directory": { "flags": ("skill_directory",), @@ -69,7 +68,6 @@ ENHANCE_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_enhance_arguments(parser: argparse.ArgumentParser) -> None: """Add all enhance command arguments to a parser.""" for arg_name, arg_def in ENHANCE_ARGUMENTS.items(): diff --git a/src/skill_seekers/cli/arguments/github.py b/src/skill_seekers/cli/arguments/github.py index 31517a6..e660f1e 100644 --- a/src/skill_seekers/cli/arguments/github.py +++ b/src/skill_seekers/cli/arguments/github.py @@ -8,11 +8,10 @@ This ensures the parsers NEVER drift out of sync. """ import argparse -from typing import Dict, Any - +from typing import Any # GitHub-specific argument definitions as data structure -GITHUB_ARGUMENTS: Dict[str, Dict[str, Any]] = { +GITHUB_ARGUMENTS: dict[str, dict[str, Any]] = { # Core GitHub options "repo": { "flags": ("--repo",), @@ -134,18 +133,17 @@ GITHUB_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_github_arguments(parser: argparse.ArgumentParser) -> None: """Add all github command arguments to a parser. - + This is the SINGLE SOURCE OF TRUTH for github arguments. Used by: - github_scraper.py (standalone scraper) - parsers/github_parser.py (unified CLI) - + Args: parser: The ArgumentParser to add arguments to - + Example: >>> parser = argparse.ArgumentParser() >>> add_github_arguments(parser) # Adds all github args @@ -155,19 +153,17 @@ def add_github_arguments(parser: argparse.ArgumentParser) -> None: kwargs = arg_def["kwargs"] parser.add_argument(*flags, **kwargs) - def get_github_argument_names() -> set: """Get the set of github argument destination names. - + Returns: Set of argument dest names """ return set(GITHUB_ARGUMENTS.keys()) - def get_github_argument_count() -> int: """Get the total number of github arguments. - + Returns: Number of arguments """ diff --git a/src/skill_seekers/cli/arguments/package.py b/src/skill_seekers/cli/arguments/package.py index 18d3df0..c3c6eab 100644 --- a/src/skill_seekers/cli/arguments/package.py +++ b/src/skill_seekers/cli/arguments/package.py @@ -6,10 +6,9 @@ import and use these definitions. """ import argparse -from typing import Dict, Any +from typing import Any - -PACKAGE_ARGUMENTS: Dict[str, Dict[str, Any]] = { +PACKAGE_ARGUMENTS: dict[str, dict[str, Any]] = { # Positional argument "skill_directory": { "flags": ("skill_directory",), @@ -124,7 +123,6 @@ PACKAGE_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_package_arguments(parser: argparse.ArgumentParser) -> None: """Add all package command arguments to a parser.""" for arg_name, arg_def in PACKAGE_ARGUMENTS.items(): diff --git a/src/skill_seekers/cli/arguments/pdf.py b/src/skill_seekers/cli/arguments/pdf.py index 9cc0154..7af93fe 100644 --- a/src/skill_seekers/cli/arguments/pdf.py +++ b/src/skill_seekers/cli/arguments/pdf.py @@ -6,10 +6,9 @@ import and use these definitions. """ import argparse -from typing import Dict, Any +from typing import Any - -PDF_ARGUMENTS: Dict[str, Dict[str, Any]] = { +PDF_ARGUMENTS: dict[str, dict[str, Any]] = { "config": { "flags": ("--config",), "kwargs": { @@ -52,7 +51,6 @@ PDF_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_pdf_arguments(parser: argparse.ArgumentParser) -> None: """Add all pdf command arguments to a parser.""" for arg_name, arg_def in PDF_ARGUMENTS.items(): diff --git a/src/skill_seekers/cli/arguments/scrape.py b/src/skill_seekers/cli/arguments/scrape.py index 963d925..9c5c976 100644 --- a/src/skill_seekers/cli/arguments/scrape.py +++ b/src/skill_seekers/cli/arguments/scrape.py @@ -8,15 +8,14 @@ This ensures the parsers NEVER drift out of sync. """ import argparse -from typing import Dict, Any +from typing import Any from skill_seekers.cli.constants import DEFAULT_RATE_LIMIT from .common import RAG_ARGUMENTS - # Scrape-specific argument definitions as data structure # This enables introspection for UI generation and testing -SCRAPE_ARGUMENTS: Dict[str, Dict[str, Any]] = { +SCRAPE_ARGUMENTS: dict[str, dict[str, Any]] = { # Positional argument "url_positional": { "flags": ("url",), @@ -199,18 +198,17 @@ SCRAPE_ARGUMENTS: Dict[str, Dict[str, Any]] = { # Merge RAG arguments from common.py SCRAPE_ARGUMENTS.update(RAG_ARGUMENTS) - def add_scrape_arguments(parser: argparse.ArgumentParser) -> None: """Add all scrape command arguments to a parser. - + This is the SINGLE SOURCE OF TRUTH for scrape arguments. Used by: - doc_scraper.py (standalone scraper) - parsers/scrape_parser.py (unified CLI) - + Args: parser: The ArgumentParser to add arguments to - + Example: >>> parser = argparse.ArgumentParser() >>> add_scrape_arguments(parser) # Adds all 26 scrape args @@ -220,19 +218,17 @@ def add_scrape_arguments(parser: argparse.ArgumentParser) -> None: kwargs = arg_def["kwargs"] parser.add_argument(*flags, **kwargs) - def get_scrape_argument_names() -> set: """Get the set of scrape argument destination names. - + Returns: Set of argument dest names """ return set(SCRAPE_ARGUMENTS.keys()) - def get_scrape_argument_count() -> int: """Get the total number of scrape arguments. - + Returns: Number of arguments """ diff --git a/src/skill_seekers/cli/arguments/unified.py b/src/skill_seekers/cli/arguments/unified.py index 6ad41ad..7c56a60 100644 --- a/src/skill_seekers/cli/arguments/unified.py +++ b/src/skill_seekers/cli/arguments/unified.py @@ -6,10 +6,9 @@ import and use these definitions. """ import argparse -from typing import Dict, Any +from typing import Any - -UNIFIED_ARGUMENTS: Dict[str, Dict[str, Any]] = { +UNIFIED_ARGUMENTS: dict[str, dict[str, Any]] = { "config": { "flags": ("--config", "-c"), "kwargs": { @@ -43,7 +42,6 @@ UNIFIED_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_unified_arguments(parser: argparse.ArgumentParser) -> None: """Add all unified command arguments to a parser.""" for arg_name, arg_def in UNIFIED_ARGUMENTS.items(): diff --git a/src/skill_seekers/cli/arguments/upload.py b/src/skill_seekers/cli/arguments/upload.py index 72b3ab3..9192199 100644 --- a/src/skill_seekers/cli/arguments/upload.py +++ b/src/skill_seekers/cli/arguments/upload.py @@ -6,10 +6,9 @@ import and use these definitions. """ import argparse -from typing import Dict, Any +from typing import Any - -UPLOAD_ARGUMENTS: Dict[str, Dict[str, Any]] = { +UPLOAD_ARGUMENTS: dict[str, dict[str, Any]] = { # Positional argument "package_file": { "flags": ("package_file",), @@ -99,7 +98,6 @@ UPLOAD_ARGUMENTS: Dict[str, Dict[str, Any]] = { }, } - def add_upload_arguments(parser: argparse.ArgumentParser) -> None: """Add all upload command arguments to a parser.""" for arg_name, arg_def in UPLOAD_ARGUMENTS.items(): diff --git a/src/skill_seekers/cli/create_command.py b/src/skill_seekers/cli/create_command.py index 9783af6..c61fc74 100644 --- a/src/skill_seekers/cli/create_command.py +++ b/src/skill_seekers/cli/create_command.py @@ -7,7 +7,6 @@ to appropriate scraper while maintaining full backward compatibility. import sys import logging import argparse -from typing import List, Optional from skill_seekers.cli.source_detector import SourceDetector, SourceInfo from skill_seekers.cli.arguments.create import ( @@ -17,7 +16,6 @@ from skill_seekers.cli.arguments.create import ( logger = logging.getLogger(__name__) - class CreateCommand: """Unified create command implementation.""" @@ -28,7 +26,7 @@ class CreateCommand: args: Parsed command-line arguments """ self.args = args - self.source_info: Optional[SourceInfo] = None + self.source_info: SourceInfo | None = None def execute(self) -> int: """Execute the create command. @@ -311,7 +309,7 @@ class CreateCommand: finally: sys.argv = original_argv - def _add_common_args(self, argv: List[str]) -> None: + def _add_common_args(self, argv: list[str]) -> None: """Add common/universal arguments to argv list. Args: @@ -367,7 +365,6 @@ class CreateCommand: if getattr(self.args, 'interactive_enhancement', False): argv.append('--interactive-enhancement') - def main() -> int: """Entry point for create command. @@ -510,6 +507,5 @@ Common Workflows: command = CreateCommand(args) return command.execute() - if __name__ == '__main__': sys.exit(main()) diff --git a/src/skill_seekers/cli/github_scraper.py b/src/skill_seekers/cli/github_scraper.py index 3a34a21..c209852 100644 --- a/src/skill_seekers/cli/github_scraper.py +++ b/src/skill_seekers/cli/github_scraper.py @@ -21,7 +21,7 @@ import os import re import sys from pathlib import Path -from typing import Any, Optional +from typing import Any try: from github import Github, GithubException, Repository @@ -100,7 +100,6 @@ EXCLUDED_DIRS = { ".tmp", } - def extract_description_from_readme(readme_content: str, repo_name: str) -> str: """ Extract a meaningful description from README content for skill description. @@ -181,7 +180,6 @@ def extract_description_from_readme(readme_content: str, repo_name: str) -> str: project_name = repo_name.split("/")[-1] return f"Use when working with {project_name}" - class GitHubScraper: """ GitHub Repository Scraper (C1.1-C1.9) @@ -563,7 +561,7 @@ class GitHubScraper: return False - def _load_gitignore(self) -> Optional["pathspec.PathSpec"]: + def _load_gitignore(self) -> "pathspec.PathSpec" | None: """ Load .gitignore file and create pathspec matcher (C2.1). @@ -894,7 +892,6 @@ class GitHubScraper: logger.info(f"Data saved to: {self.data_file}") - class GitHubToSkillConverter: """ Convert extracted GitHub data to Claude skill format (C1.10). @@ -1350,14 +1347,13 @@ Use this skill when you need to: f.write(content) logger.info(f"Generated: {structure_path}") - def setup_argument_parser() -> argparse.ArgumentParser: """Setup and configure command-line argument parser. - + Creates an ArgumentParser with all CLI options for the github scraper. All arguments are defined in skill_seekers.cli.arguments.github to ensure consistency between the standalone scraper and unified CLI. - + Returns: argparse.ArgumentParser: Configured argument parser """ @@ -1378,7 +1374,6 @@ Examples: return parser - def main(): """C1.10: CLI tool entry point.""" parser = setup_argument_parser() @@ -1476,6 +1471,5 @@ def main(): logger.error(f"Error: {e}") sys.exit(1) - if __name__ == "__main__": main() diff --git a/src/skill_seekers/cli/parsers/__init__.py b/src/skill_seekers/cli/parsers/__init__.py index f9d392b..c4737c3 100644 --- a/src/skill_seekers/cli/parsers/__init__.py +++ b/src/skill_seekers/cli/parsers/__init__.py @@ -28,7 +28,6 @@ from .update_parser import UpdateParser from .multilang_parser import MultilangParser from .quality_parser import QualityParser - # Registry of all parsers (in order of usage frequency) PARSERS = [ CreateParser(), # NEW: Unified create command (placed first for prominence) @@ -53,7 +52,6 @@ PARSERS = [ QualityParser(), ] - def register_parsers(subparsers): """Register all subcommand parsers. @@ -66,7 +64,6 @@ def register_parsers(subparsers): for parser_instance in PARSERS: parser_instance.create_parser(subparsers) - def get_parser_names(): """Get list of all subcommand names. @@ -75,7 +72,6 @@ def get_parser_names(): """ return [p.name for p in PARSERS] - __all__ = [ "SubcommandParser", "PARSERS", diff --git a/src/skill_seekers/cli/parsers/analyze_parser.py b/src/skill_seekers/cli/parsers/analyze_parser.py index db52200..897e302 100644 --- a/src/skill_seekers/cli/parsers/analyze_parser.py +++ b/src/skill_seekers/cli/parsers/analyze_parser.py @@ -9,7 +9,6 @@ Includes preset system support (Issue #268). from .base import SubcommandParser from skill_seekers.cli.arguments.analyze import add_analyze_arguments - class AnalyzeParser(SubcommandParser): """Parser for analyze subcommand.""" @@ -27,10 +26,10 @@ class AnalyzeParser(SubcommandParser): def add_arguments(self, parser): """Add analyze-specific arguments. - + Uses shared argument definitions to ensure consistency with codebase_scraper.py (standalone scraper). - + Includes preset system for simplified UX. """ add_analyze_arguments(parser) diff --git a/src/skill_seekers/cli/parsers/base.py b/src/skill_seekers/cli/parsers/base.py index 765cf01..45e57ad 100644 --- a/src/skill_seekers/cli/parsers/base.py +++ b/src/skill_seekers/cli/parsers/base.py @@ -3,7 +3,6 @@ from abc import ABC, abstractmethod import argparse - class SubcommandParser(ABC): """Base class for subcommand parsers. diff --git a/src/skill_seekers/cli/parsers/config_parser.py b/src/skill_seekers/cli/parsers/config_parser.py index f78c36e..d46aba0 100644 --- a/src/skill_seekers/cli/parsers/config_parser.py +++ b/src/skill_seekers/cli/parsers/config_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class ConfigParser(SubcommandParser): """Parser for config subcommand.""" diff --git a/src/skill_seekers/cli/parsers/create_parser.py b/src/skill_seekers/cli/parsers/create_parser.py index 1f0244c..e1f59a9 100644 --- a/src/skill_seekers/cli/parsers/create_parser.py +++ b/src/skill_seekers/cli/parsers/create_parser.py @@ -13,7 +13,6 @@ import argparse from .base import SubcommandParser from skill_seekers.cli.arguments.create import add_create_arguments - class CreateParser(SubcommandParser): """Parser for create subcommand with multi-mode help.""" diff --git a/src/skill_seekers/cli/parsers/enhance_parser.py b/src/skill_seekers/cli/parsers/enhance_parser.py index 6bfe51d..bd15163 100644 --- a/src/skill_seekers/cli/parsers/enhance_parser.py +++ b/src/skill_seekers/cli/parsers/enhance_parser.py @@ -7,7 +7,6 @@ consistency with the standalone enhance_skill_local module. from .base import SubcommandParser from skill_seekers.cli.arguments.enhance import add_enhance_arguments - class EnhanceParser(SubcommandParser): """Parser for enhance subcommand.""" @@ -25,7 +24,7 @@ class EnhanceParser(SubcommandParser): def add_arguments(self, parser): """Add enhance-specific arguments. - + Uses shared argument definitions to ensure consistency with enhance_skill_local.py (standalone enhancer). """ diff --git a/src/skill_seekers/cli/parsers/enhance_status_parser.py b/src/skill_seekers/cli/parsers/enhance_status_parser.py index 229098c..119ba31 100644 --- a/src/skill_seekers/cli/parsers/enhance_status_parser.py +++ b/src/skill_seekers/cli/parsers/enhance_status_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class EnhanceStatusParser(SubcommandParser): """Parser for enhance-status subcommand.""" diff --git a/src/skill_seekers/cli/parsers/estimate_parser.py b/src/skill_seekers/cli/parsers/estimate_parser.py index 5a21bdc..e699058 100644 --- a/src/skill_seekers/cli/parsers/estimate_parser.py +++ b/src/skill_seekers/cli/parsers/estimate_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class EstimateParser(SubcommandParser): """Parser for estimate subcommand.""" diff --git a/src/skill_seekers/cli/parsers/github_parser.py b/src/skill_seekers/cli/parsers/github_parser.py index 742c097..e7ea2f7 100644 --- a/src/skill_seekers/cli/parsers/github_parser.py +++ b/src/skill_seekers/cli/parsers/github_parser.py @@ -7,7 +7,6 @@ consistency with the standalone github_scraper module. from .base import SubcommandParser from skill_seekers.cli.arguments.github import add_github_arguments - class GitHubParser(SubcommandParser): """Parser for github subcommand.""" @@ -25,7 +24,7 @@ class GitHubParser(SubcommandParser): def add_arguments(self, parser): """Add github-specific arguments. - + Uses shared argument definitions to ensure consistency with github_scraper.py (standalone scraper). """ diff --git a/src/skill_seekers/cli/parsers/install_agent_parser.py b/src/skill_seekers/cli/parsers/install_agent_parser.py index 884d56e..dcc1803 100644 --- a/src/skill_seekers/cli/parsers/install_agent_parser.py +++ b/src/skill_seekers/cli/parsers/install_agent_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class InstallAgentParser(SubcommandParser): """Parser for install-agent subcommand.""" diff --git a/src/skill_seekers/cli/parsers/install_parser.py b/src/skill_seekers/cli/parsers/install_parser.py index 3d48e6d..6bb06e8 100644 --- a/src/skill_seekers/cli/parsers/install_parser.py +++ b/src/skill_seekers/cli/parsers/install_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class InstallParser(SubcommandParser): """Parser for install subcommand.""" diff --git a/src/skill_seekers/cli/parsers/multilang_parser.py b/src/skill_seekers/cli/parsers/multilang_parser.py index 68bdb55..2de4c8f 100644 --- a/src/skill_seekers/cli/parsers/multilang_parser.py +++ b/src/skill_seekers/cli/parsers/multilang_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class MultilangParser(SubcommandParser): """Parser for multilang subcommand.""" diff --git a/src/skill_seekers/cli/parsers/package_parser.py b/src/skill_seekers/cli/parsers/package_parser.py index f6cc0c3..0511459 100644 --- a/src/skill_seekers/cli/parsers/package_parser.py +++ b/src/skill_seekers/cli/parsers/package_parser.py @@ -7,7 +7,6 @@ consistency with the standalone package_skill module. from .base import SubcommandParser from skill_seekers.cli.arguments.package import add_package_arguments - class PackageParser(SubcommandParser): """Parser for package subcommand.""" @@ -25,7 +24,7 @@ class PackageParser(SubcommandParser): def add_arguments(self, parser): """Add package-specific arguments. - + Uses shared argument definitions to ensure consistency with package_skill.py (standalone packager). """ diff --git a/src/skill_seekers/cli/parsers/pdf_parser.py b/src/skill_seekers/cli/parsers/pdf_parser.py index 503b476..3c9f0d6 100644 --- a/src/skill_seekers/cli/parsers/pdf_parser.py +++ b/src/skill_seekers/cli/parsers/pdf_parser.py @@ -7,7 +7,6 @@ consistency with the standalone pdf_scraper module. from .base import SubcommandParser from skill_seekers.cli.arguments.pdf import add_pdf_arguments - class PDFParser(SubcommandParser): """Parser for pdf subcommand.""" @@ -25,7 +24,7 @@ class PDFParser(SubcommandParser): def add_arguments(self, parser): """Add pdf-specific arguments. - + Uses shared argument definitions to ensure consistency with pdf_scraper.py (standalone scraper). """ diff --git a/src/skill_seekers/cli/parsers/quality_parser.py b/src/skill_seekers/cli/parsers/quality_parser.py index 69803fe..e394cba 100644 --- a/src/skill_seekers/cli/parsers/quality_parser.py +++ b/src/skill_seekers/cli/parsers/quality_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class QualityParser(SubcommandParser): """Parser for quality subcommand.""" diff --git a/src/skill_seekers/cli/parsers/resume_parser.py b/src/skill_seekers/cli/parsers/resume_parser.py index 9bb5d07..f024d2a 100644 --- a/src/skill_seekers/cli/parsers/resume_parser.py +++ b/src/skill_seekers/cli/parsers/resume_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class ResumeParser(SubcommandParser): """Parser for resume subcommand.""" diff --git a/src/skill_seekers/cli/parsers/scrape_parser.py b/src/skill_seekers/cli/parsers/scrape_parser.py index 8b686fe..83cbea9 100644 --- a/src/skill_seekers/cli/parsers/scrape_parser.py +++ b/src/skill_seekers/cli/parsers/scrape_parser.py @@ -7,7 +7,6 @@ consistency with the standalone doc_scraper module. from .base import SubcommandParser from skill_seekers.cli.arguments.scrape import add_scrape_arguments - class ScrapeParser(SubcommandParser): """Parser for scrape subcommand.""" @@ -25,7 +24,7 @@ class ScrapeParser(SubcommandParser): def add_arguments(self, parser): """Add scrape-specific arguments. - + Uses shared argument definitions to ensure consistency with doc_scraper.py (standalone scraper). """ diff --git a/src/skill_seekers/cli/parsers/stream_parser.py b/src/skill_seekers/cli/parsers/stream_parser.py index 6ee513a..79f7cfc 100644 --- a/src/skill_seekers/cli/parsers/stream_parser.py +++ b/src/skill_seekers/cli/parsers/stream_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class StreamParser(SubcommandParser): """Parser for stream subcommand.""" diff --git a/src/skill_seekers/cli/parsers/test_examples_parser.py b/src/skill_seekers/cli/parsers/test_examples_parser.py index da2bde9..68df0ed 100644 --- a/src/skill_seekers/cli/parsers/test_examples_parser.py +++ b/src/skill_seekers/cli/parsers/test_examples_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class TestExamplesParser(SubcommandParser): """Parser for extract-test-examples subcommand.""" diff --git a/src/skill_seekers/cli/parsers/unified_parser.py b/src/skill_seekers/cli/parsers/unified_parser.py index f5eec9a..c6ee77a 100644 --- a/src/skill_seekers/cli/parsers/unified_parser.py +++ b/src/skill_seekers/cli/parsers/unified_parser.py @@ -7,7 +7,6 @@ consistency with the standalone unified_scraper module. from .base import SubcommandParser from skill_seekers.cli.arguments.unified import add_unified_arguments - class UnifiedParser(SubcommandParser): """Parser for unified subcommand.""" @@ -25,7 +24,7 @@ class UnifiedParser(SubcommandParser): def add_arguments(self, parser): """Add unified-specific arguments. - + Uses shared argument definitions to ensure consistency with unified_scraper.py (standalone scraper). """ diff --git a/src/skill_seekers/cli/parsers/update_parser.py b/src/skill_seekers/cli/parsers/update_parser.py index eaa321a..46711f4 100644 --- a/src/skill_seekers/cli/parsers/update_parser.py +++ b/src/skill_seekers/cli/parsers/update_parser.py @@ -2,7 +2,6 @@ from .base import SubcommandParser - class UpdateParser(SubcommandParser): """Parser for update subcommand.""" diff --git a/src/skill_seekers/cli/parsers/upload_parser.py b/src/skill_seekers/cli/parsers/upload_parser.py index 09006d3..4aff69c 100644 --- a/src/skill_seekers/cli/parsers/upload_parser.py +++ b/src/skill_seekers/cli/parsers/upload_parser.py @@ -7,7 +7,6 @@ consistency with the standalone upload_skill module. from .base import SubcommandParser from skill_seekers.cli.arguments.upload import add_upload_arguments - class UploadParser(SubcommandParser): """Parser for upload subcommand.""" @@ -25,7 +24,7 @@ class UploadParser(SubcommandParser): def add_arguments(self, parser): """Add upload-specific arguments. - + Uses shared argument definitions to ensure consistency with upload_skill.py (standalone uploader). """ diff --git a/src/skill_seekers/cli/presets/__init__.py b/src/skill_seekers/cli/presets/__init__.py index 386f33a..3fccef7 100644 --- a/src/skill_seekers/cli/presets/__init__.py +++ b/src/skill_seekers/cli/presets/__init__.py @@ -20,7 +20,6 @@ from .manager import ( # Analyze presets from .analyze_presets import ( - AnalysisPreset as AnalyzeAnalysisPreset, # Alternative version (without enhance_level) ANALYZE_PRESETS, apply_analyze_preset, get_preset_help_text, diff --git a/src/skill_seekers/cli/presets/analyze_presets.py b/src/skill_seekers/cli/presets/analyze_presets.py index a3f3548..a2949fe 100644 --- a/src/skill_seekers/cli/presets/analyze_presets.py +++ b/src/skill_seekers/cli/presets/analyze_presets.py @@ -12,17 +12,16 @@ Examples: """ from dataclasses import dataclass, field -from typing import Dict, Optional -import argparse +import argparse @dataclass(frozen=True) class AnalysisPreset: """Definition of an analysis preset. - + Presets control analysis depth and features ONLY. AI Enhancement is controlled separately via --enhance or --enhance-level. - + Attributes: name: Human-readable preset name description: Brief description of what this preset does @@ -33,10 +32,9 @@ class AnalysisPreset: name: str description: str depth: str - features: Dict[str, bool] = field(default_factory=dict) + features: dict[str, bool] = field(default_factory=dict) estimated_time: str = "" - # Preset definitions ANALYZE_PRESETS = { "quick": AnalysisPreset( @@ -53,7 +51,7 @@ ANALYZE_PRESETS = { }, estimated_time="1-2 minutes" ), - + "standard": AnalysisPreset( name="Standard", description="Balanced analysis with core features (recommended)", @@ -68,7 +66,7 @@ ANALYZE_PRESETS = { }, estimated_time="5-10 minutes" ), - + "comprehensive": AnalysisPreset( name="Comprehensive", description="Full analysis with all features", @@ -85,21 +83,20 @@ ANALYZE_PRESETS = { ), } - def apply_analyze_preset(args: argparse.Namespace, preset_name: str) -> None: """Apply an analysis preset to the args namespace. - + This modifies the args object to set the preset's depth and feature flags. NOTE: This does NOT set enhance_level - that's controlled separately via --enhance or --enhance-level flags. - + Args: args: The argparse.Namespace to modify preset_name: Name of the preset to apply - + Raises: KeyError: If preset_name is not a valid preset - + Example: >>> args = parser.parse_args(['--directory', '.', '--preset', 'quick']) >>> apply_analyze_preset(args, args.preset) @@ -107,22 +104,21 @@ def apply_analyze_preset(args: argparse.Namespace, preset_name: str) -> None: >>> # enhance_level is still 0 (default) unless --enhance was specified """ preset = ANALYZE_PRESETS[preset_name] - + # Set depth args.depth = preset.depth - + # Set feature flags (skip_* attributes) for feature, enabled in preset.features.items(): skip_attr = f"skip_{feature}" setattr(args, skip_attr, not enabled) - def get_preset_help_text(preset_name: str) -> str: """Get formatted help text for a preset. - + Args: preset_name: Name of the preset - + Returns: Formatted help string """ @@ -133,29 +129,28 @@ def get_preset_help_text(preset_name: str) -> str: f" Depth: {preset.depth}" ) - def show_preset_list() -> None: """Print the list of available presets to stdout. - + This is used by the --preset-list flag. """ print("\nAvailable Analysis Presets") print("=" * 60) print() - + for name, preset in ANALYZE_PRESETS.items(): marker = " (DEFAULT)" if name == "standard" else "" print(f" {name}{marker}") print(f" {preset.description}") print(f" Estimated time: {preset.estimated_time}") print(f" Depth: {preset.depth}") - + # Show enabled features enabled = [f for f, v in preset.features.items() if v] if enabled: print(f" Features: {', '.join(enabled)}") print() - + print("AI Enhancement (separate from presets):") print(" --enhance Enable AI enhancement (default level 1)") print(" --enhance-level N Set AI enhancement level (0-3)") @@ -166,91 +161,88 @@ def show_preset_list() -> None: print(" skill-seekers analyze --directory --preset comprehensive --enhance-level 2") print() - def resolve_enhance_level(args: argparse.Namespace) -> int: """Determine the enhance level based on user arguments. - + This is separate from preset application. Enhance level is controlled by: - --enhance-level N (explicit) - --enhance (use default level 1) - Neither (default to 0) - + Args: args: Parsed command-line arguments - + Returns: The enhance level to use (0-3) """ # Explicit enhance level takes priority if args.enhance_level is not None: return args.enhance_level - + # --enhance flag enables default level (1) if args.enhance: return 1 - + # Default is no enhancement return 0 - def apply_preset_with_warnings(args: argparse.Namespace) -> str: """Apply preset with deprecation warnings for legacy flags. - + This is the main entry point for applying presets. It: 1. Determines which preset to use 2. Prints deprecation warnings if legacy flags were used 3. Applies the preset (depth and features only) 4. Sets enhance_level separately based on --enhance/--enhance-level 5. Returns the preset name - + Args: args: Parsed command-line arguments - + Returns: The preset name that was applied """ preset_name = None - + # Check for explicit preset if args.preset: preset_name = args.preset - + # Check for legacy flags and print warnings elif args.quick: print_deprecation_warning("--quick", "--preset quick") preset_name = "quick" - + elif args.comprehensive: print_deprecation_warning("--comprehensive", "--preset comprehensive") preset_name = "comprehensive" - + elif args.depth: depth_to_preset = { "surface": "quick", - "deep": "standard", + "deep": "standard", "full": "comprehensive", } if args.depth in depth_to_preset: new_flag = f"--preset {depth_to_preset[args.depth]}" print_deprecation_warning(f"--depth {args.depth}", new_flag) preset_name = depth_to_preset[args.depth] - + # Default to standard if preset_name is None: preset_name = "standard" - + # Apply the preset (depth and features only) apply_analyze_preset(args, preset_name) - + # Set enhance_level separately (not part of preset) args.enhance_level = resolve_enhance_level(args) - - return preset_name + return preset_name def print_deprecation_warning(old_flag: str, new_flag: str) -> None: """Print a deprecation warning for legacy flags. - + Args: old_flag: The old/deprecated flag name new_flag: The new recommended flag/preset diff --git a/src/skill_seekers/cli/presets/github_presets.py b/src/skill_seekers/cli/presets/github_presets.py index 1a29fa0..9f034aa 100644 --- a/src/skill_seekers/cli/presets/github_presets.py +++ b/src/skill_seekers/cli/presets/github_presets.py @@ -9,14 +9,13 @@ Presets: """ from dataclasses import dataclass, field -from typing import Dict -import argparse +import argparse @dataclass(frozen=True) class GitHubPreset: """Definition of a GitHub preset. - + Attributes: name: Human-readable preset name description: Brief description of what this preset does @@ -27,10 +26,9 @@ class GitHubPreset: name: str description: str max_issues: int - features: Dict[str, bool] = field(default_factory=dict) + features: dict[str, bool] = field(default_factory=dict) estimated_time: str = "" - # Preset definitions GITHUB_PRESETS = { "quick": GitHubPreset( @@ -44,7 +42,7 @@ GITHUB_PRESETS = { }, estimated_time="1-3 minutes" ), - + "standard": GitHubPreset( name="Standard", description="Balanced scraping with issues and releases (recommended)", @@ -56,7 +54,7 @@ GITHUB_PRESETS = { }, estimated_time="5-15 minutes" ), - + "comprehensive": GitHubPreset( name="Comprehensive", description="Comprehensive scraping with all available data", @@ -70,48 +68,46 @@ GITHUB_PRESETS = { ), } - def apply_github_preset(args: argparse.Namespace, preset_name: str) -> None: """Apply a GitHub preset to the args namespace. - + Args: args: The argparse.Namespace to modify preset_name: Name of the preset to apply - + Raises: KeyError: If preset_name is not a valid preset """ preset = GITHUB_PRESETS[preset_name] - + # Apply max_issues only if not set by user if args.max_issues is None or args.max_issues == 100: # 100 is default args.max_issues = preset.max_issues - + # Apply feature flags (only if not explicitly disabled by user) for feature, enabled in preset.features.items(): skip_attr = f"no_{feature}" if not hasattr(args, skip_attr) or not getattr(args, skip_attr): setattr(args, skip_attr, not enabled) - def show_github_preset_list() -> None: """Print the list of available GitHub presets to stdout.""" print("\nAvailable GitHub Presets") print("=" * 60) print() - + for name, preset in GITHUB_PRESETS.items(): marker = " (DEFAULT)" if name == "standard" else "" print(f" {name}{marker}") print(f" {preset.description}") print(f" Estimated time: {preset.estimated_time}") print(f" Max issues: {preset.max_issues}") - + # Show enabled features enabled = [f.replace("include_", "") for f, v in preset.features.items() if v] if enabled: print(f" Features: {', '.join(enabled)}") print() - + print("Usage: skill-seekers github --repo --preset ") print() diff --git a/src/skill_seekers/cli/presets/manager.py b/src/skill_seekers/cli/presets/manager.py index 55b573c..15bed25 100644 --- a/src/skill_seekers/cli/presets/manager.py +++ b/src/skill_seekers/cli/presets/manager.py @@ -6,7 +6,6 @@ between speed and comprehensiveness. from dataclasses import dataclass - @dataclass class AnalysisPreset: """Analysis preset configuration. @@ -23,7 +22,6 @@ class AnalysisPreset: estimated_time: str icon: str - # Preset definitions PRESETS = { "quick": AnalysisPreset( @@ -79,7 +77,6 @@ PRESETS = { ), } - class PresetManager: """Manages analysis presets and applies them to CLI arguments.""" @@ -167,7 +164,6 @@ class PresetManager: """ return "standard" - # Public API __all__ = [ "AnalysisPreset", diff --git a/src/skill_seekers/cli/presets/scrape_presets.py b/src/skill_seekers/cli/presets/scrape_presets.py index 4a272dc..e81f638 100644 --- a/src/skill_seekers/cli/presets/scrape_presets.py +++ b/src/skill_seekers/cli/presets/scrape_presets.py @@ -9,14 +9,13 @@ Presets: """ from dataclasses import dataclass, field -from typing import Dict, Optional -import argparse +import argparse @dataclass(frozen=True) class ScrapePreset: """Definition of a scrape preset. - + Attributes: name: Human-readable preset name description: Brief description of what this preset does @@ -29,12 +28,11 @@ class ScrapePreset: name: str description: str rate_limit: float - features: Dict[str, bool] = field(default_factory=dict) + features: dict[str, bool] = field(default_factory=dict) async_mode: bool = False workers: int = 1 estimated_time: str = "" - # Preset definitions SCRAPE_PRESETS = { "quick": ScrapePreset( @@ -49,7 +47,7 @@ SCRAPE_PRESETS = { workers=5, estimated_time="2-5 minutes" ), - + "standard": ScrapePreset( name="Standard", description="Balanced scraping with good coverage (recommended)", @@ -62,7 +60,7 @@ SCRAPE_PRESETS = { workers=3, estimated_time="10-30 minutes" ), - + "comprehensive": ScrapePreset( name="Comprehensive", description="Comprehensive scraping with all features", @@ -77,43 +75,40 @@ SCRAPE_PRESETS = { ), } - def apply_scrape_preset(args: argparse.Namespace, preset_name: str) -> None: """Apply a scrape preset to the args namespace. - + Args: args: The argparse.Namespace to modify preset_name: Name of the preset to apply - + Raises: KeyError: If preset_name is not a valid preset """ preset = SCRAPE_PRESETS[preset_name] - + # Apply rate limit (only if not set by user) if args.rate_limit is None: args.rate_limit = preset.rate_limit - + # Apply workers (only if not set by user) if args.workers is None: args.workers = preset.workers - + # Apply async mode args.async_mode = preset.async_mode - + # Apply feature flags for feature, enabled in preset.features.items(): - if feature == "rag_chunking": - if not hasattr(args, 'chunk_for_rag') or not args.chunk_for_rag: - args.chunk_for_rag = enabled - + if feature == "rag_chunking" and (not hasattr(args, 'chunk_for_rag') or not args.chunk_for_rag): + args.chunk_for_rag = enabled def show_scrape_preset_list() -> None: """Print the list of available scrape presets to stdout.""" print("\nAvailable Scrape Presets") print("=" * 60) print() - + for name, preset in SCRAPE_PRESETS.items(): marker = " (DEFAULT)" if name == "standard" else "" print(f" {name}{marker}") @@ -122,6 +117,6 @@ def show_scrape_preset_list() -> None: print(f" Workers: {preset.workers}") print(f" Async: {preset.async_mode}, Rate limit: {preset.rate_limit}s") print() - + print("Usage: skill-seekers scrape --preset ") print() diff --git a/src/skill_seekers/cli/source_detector.py b/src/skill_seekers/cli/source_detector.py index d64efcd..1d1f443 100644 --- a/src/skill_seekers/cli/source_detector.py +++ b/src/skill_seekers/cli/source_detector.py @@ -7,13 +7,12 @@ local directory, PDF file, or config file based on patterns. import os import re from dataclasses import dataclass -from typing import Dict, Any, Optional +from typing import Any from urllib.parse import urlparse import logging logger = logging.getLogger(__name__) - @dataclass class SourceInfo: """Information about a detected source. @@ -25,11 +24,10 @@ class SourceInfo: raw_input: Original user input """ type: str - parsed: Dict[str, Any] + parsed: dict[str, Any] suggested_name: str raw_input: str - class SourceDetector: """Detects source type from user input and extracts relevant information.""" @@ -124,7 +122,7 @@ class SourceDetector: ) @classmethod - def _detect_github(cls, source: str) -> Optional[SourceInfo]: + def _detect_github(cls, source: str) -> SourceInfo | None: """Detect GitHub repository source. Supports patterns: diff --git a/tests/test_cli_refactor_e2e.py b/tests/test_cli_refactor_e2e.py index 6052f97..e60a783 100644 --- a/tests/test_cli_refactor_e2e.py +++ b/tests/test_cli_refactor_e2e.py @@ -12,9 +12,6 @@ These tests verify that the unified CLI architecture works correctly: import pytest import subprocess import argparse -import sys -from pathlib import Path - class TestParserSync: """E2E tests for parser synchronization (Issue #285).""" @@ -77,7 +74,6 @@ class TestParserSync: for flag in expected_flags: assert flag in result.stdout, f"Help should show {flag} flag" - class TestPresetSystem: """E2E tests for preset system (Issue #268).""" @@ -141,7 +137,6 @@ class TestPresetSystem: assert "DEPRECATED" in output, "Should show deprecation warning" assert "--preset comprehensive" in output, "Should suggest alternative" - class TestBackwardCompatibility: """E2E tests for backward compatibility.""" @@ -185,7 +180,6 @@ class TestBackwardCompatibility: assert flag in unified_result.stdout, f"Unified should have {flag}" assert flag in standalone_result.stdout, f"Standalone should have {flag}" - class TestProgrammaticAPI: """Test that the shared argument functions work programmatically.""" @@ -227,7 +221,6 @@ class TestProgrammaticAPI: # Note: enhance_level is not part of AnalysisPreset anymore. # It's controlled separately via --enhance-level flag (default 2) - class TestIntegration: """Integration tests for the complete flow.""" @@ -278,7 +271,6 @@ class TestIntegration: assert "--preset" in result.stdout, "Should show --preset flag" assert "DEFAULT" in result.stdout or "default" in result.stdout, "Should indicate default preset" - class TestE2EWorkflow: """End-to-end workflow tests.""" @@ -322,6 +314,5 @@ class TestE2EWorkflow: assert "--preset" in result.stdout, "Should have --preset flag" assert "unrecognized arguments" not in result.stderr.lower() - if __name__ == "__main__": pytest.main([__file__, "-v", "-s"]) diff --git a/tests/test_create_arguments.py b/tests/test_create_arguments.py index affbc31..d55160c 100644 --- a/tests/test_create_arguments.py +++ b/tests/test_create_arguments.py @@ -6,7 +6,6 @@ Tests the three-tier argument system: 3. Advanced arguments """ -import pytest from skill_seekers.cli.arguments.create import ( UNIVERSAL_ARGUMENTS, WEB_ARGUMENTS, @@ -20,7 +19,6 @@ from skill_seekers.cli.arguments.create import ( add_create_arguments, ) - class TestUniversalArguments: """Test universal argument definitions.""" @@ -51,7 +49,6 @@ class TestUniversalArguments: assert 'kwargs' in arg_def assert 'help' in arg_def['kwargs'] - class TestSourceSpecificArguments: """Test source-specific argument definitions.""" @@ -96,7 +93,6 @@ class TestSourceSpecificArguments: assert flag not in all_flags, f"Duplicate flag: {flag}" all_flags.add(flag) - class TestAdvancedArguments: """Test advanced/rare argument definitions.""" @@ -106,7 +102,6 @@ class TestAdvancedArguments: assert 'no_rate_limit' in ADVANCED_ARGUMENTS assert 'interactive_enhancement' in ADVANCED_ARGUMENTS - class TestArgumentHelpers: """Test helper functions.""" @@ -148,7 +143,6 @@ class TestArgumentHelpers: args = get_source_specific_arguments('unknown') assert args == {} - class TestCompatibleArguments: """Test compatible argument detection.""" @@ -217,7 +211,6 @@ class TestCompatibleArguments: assert 'repo' not in compatible assert 'directory' not in compatible - class TestAddCreateArguments: """Test add_create_arguments function.""" @@ -284,7 +277,6 @@ class TestAddCreateArguments: args = parser.parse_args(['some_source']) assert args.source == 'some_source' - class TestNoDuplicates: """Test that there are no duplicate arguments across tiers.""" @@ -320,7 +312,6 @@ class TestNoDuplicates: assert len(github_flags & pdf_flags) == 0 assert len(local_flags & pdf_flags) == 0 - class TestArgumentQuality: """Test argument definition quality.""" diff --git a/tests/test_create_integration_basic.py b/tests/test_create_integration_basic.py index d3c1d0a..621cf4f 100644 --- a/tests/test_create_integration_basic.py +++ b/tests/test_create_integration_basic.py @@ -5,10 +5,6 @@ and routes to the correct scrapers without actually scraping. """ import pytest -import tempfile -import os -from pathlib import Path - class TestCreateCommandBasic: """Basic integration tests for create command (dry-run mode).""" @@ -124,7 +120,6 @@ class TestCreateCommandBasic: assert '--preset' in result.stdout assert '--dry-run' in result.stdout - class TestBackwardCompatibility: """Test that old commands still work.""" diff --git a/tests/test_parser_sync.py b/tests/test_parser_sync.py index 73ce424..39cb3c0 100644 --- a/tests/test_parser_sync.py +++ b/tests/test_parser_sync.py @@ -6,8 +6,6 @@ the same arguments as the standalone scraper modules. This prevents the """ import argparse -import pytest - class TestScrapeParserSync: """Ensure scrape_parser has all arguments from doc_scraper.""" @@ -87,7 +85,6 @@ class TestScrapeParserSync: for arg in required_args: assert arg in arg_dests, f"Required argument '{arg}' missing from scrape parser" - class TestGitHubParserSync: """Ensure github_parser has all arguments from github_scraper.""" @@ -131,7 +128,6 @@ class TestGitHubParserSync: assert not missing, f"github_parser missing arguments: {missing}" assert not extra, f"github_parser has extra arguments not in github_scraper: {extra}" - class TestUnifiedCLI: """Test the unified CLI main parser.""" diff --git a/tests/test_source_detector.py b/tests/test_source_detector.py index 6be8a06..d402333 100644 --- a/tests/test_source_detector.py +++ b/tests/test_source_detector.py @@ -9,13 +9,10 @@ Tests the SourceDetector class's ability to identify and parse: """ import os -import tempfile import pytest -from pathlib import Path from skill_seekers.cli.source_detector import SourceDetector, SourceInfo - class TestWebDetection: """Test web URL detection.""" @@ -58,7 +55,6 @@ class TestWebDetection: assert info.type == 'web' assert info.suggested_name == 'vue' - class TestGitHubDetection: """Test GitHub repository detection.""" @@ -97,7 +93,6 @@ class TestGitHubDetection: assert info.parsed['repo'] == "microsoft/vscode-python" assert info.suggested_name == 'vscode-python' - class TestLocalDetection: """Test local directory detection.""" @@ -136,7 +131,6 @@ class TestLocalDetection: assert info.type == 'local' assert info.parsed['directory'] == cwd - class TestPDFDetection: """Test PDF file detection.""" @@ -160,7 +154,6 @@ class TestPDFDetection: assert info.type == 'pdf' assert info.suggested_name == 'my-awesome-guide' - class TestConfigDetection: """Test config file detection.""" @@ -178,7 +171,6 @@ class TestConfigDetection: assert info.parsed['config_path'] == "configs/django.json" assert info.suggested_name == 'django' - class TestValidation: """Test source validation.""" @@ -246,7 +238,6 @@ class TestValidation: ) SourceDetector.validate_source(info) - class TestAmbiguousCases: """Test handling of ambiguous inputs.""" @@ -277,7 +268,6 @@ class TestAmbiguousCases: # Should detect as local directory, not web assert info.type == 'local' - class TestRawInputPreservation: """Test that raw_input is preserved correctly.""" @@ -302,7 +292,6 @@ class TestRawInputPreservation: info = SourceDetector.detect(original) assert info.raw_input == original - class TestEdgeCases: """Test edge cases and corner cases."""