merge: Sync main into development - includes Task 1.1 and 1.2 fixes

This commit is contained in:
yusyus
2025-11-29 21:59:36 +03:00
5 changed files with 38 additions and 44 deletions

View File

@@ -33,7 +33,7 @@ except ImportError:
# Import code analyzer for deep code analysis # Import code analyzer for deep code analysis
try: try:
from code_analyzer import CodeAnalyzer from .code_analyzer import CodeAnalyzer
CODE_ANALYZER_AVAILABLE = True CODE_ANALYZER_AVAILABLE = True
except ImportError: except ImportError:
CODE_ANALYZER_AVAILABLE = False CODE_ANALYZER_AVAILABLE = False

View File

@@ -19,7 +19,7 @@ import argparse
from pathlib import Path from pathlib import Path
# Import the PDF extractor # Import the PDF extractor
from pdf_extractor_poc import PDFExtractor from .pdf_extractor_poc import PDFExtractor
class PDFToSkillConverter: class PDFToSkillConverter:

View File

@@ -14,7 +14,7 @@ from pathlib import Path
# Add CLI to path # Add CLI to path
sys.path.insert(0, str(Path(__file__).parent)) sys.path.insert(0, str(Path(__file__).parent))
from config_validator import validate_config from .config_validator import validate_config
def test_validate_existing_unified_configs(): def test_validate_existing_unified_configs():
"""Test that all existing unified configs are valid""" """Test that all existing unified configs are valid"""

View File

@@ -24,9 +24,6 @@ from pathlib import Path
from unittest.mock import Mock, patch, MagicMock from unittest.mock import Mock, patch, MagicMock
from datetime import datetime from datetime import datetime
# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent / "cli"))
try: try:
from github import Github, GithubException from github import Github, GithubException
PYGITHUB_AVAILABLE = True PYGITHUB_AVAILABLE = True
@@ -40,7 +37,7 @@ class TestGitHubScraperInitialization(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubScraper from skill_seekers.cli.github_scraper import GitHubScraper
self.GitHubScraper = GitHubScraper self.GitHubScraper = GitHubScraper
# Create temporary directory for test output # Create temporary directory for test output
@@ -74,7 +71,7 @@ class TestGitHubScraperInitialization(unittest.TestCase):
'github_token': 'test_token_123' 'github_token': 'test_token_123'
} }
with patch('github_scraper.Github') as mock_github: with patch('skill_seekers.cli.github_scraper.Github') as mock_github:
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
mock_github.assert_called_once_with('test_token_123') mock_github.assert_called_once_with('test_token_123')
@@ -87,7 +84,7 @@ class TestGitHubScraperInitialization(unittest.TestCase):
} }
with patch.dict(os.environ, {'GITHUB_TOKEN': 'env_token_456'}): with patch.dict(os.environ, {'GITHUB_TOKEN': 'env_token_456'}):
with patch('github_scraper.Github') as mock_github: with patch('skill_seekers.cli.github_scraper.Github') as mock_github:
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
mock_github.assert_called_once_with('env_token_456') mock_github.assert_called_once_with('env_token_456')
@@ -99,7 +96,7 @@ class TestGitHubScraperInitialization(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github') as mock_github: with patch('skill_seekers.cli.github_scraper.Github') as mock_github:
with patch.dict(os.environ, {}, clear=True): with patch.dict(os.environ, {}, clear=True):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
# Should create unauthenticated client # Should create unauthenticated client
@@ -125,7 +122,7 @@ class TestREADMEExtraction(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubScraper from skill_seekers.cli.github_scraper import GitHubScraper
self.GitHubScraper = GitHubScraper self.GitHubScraper = GitHubScraper
def test_extract_readme_success(self): def test_extract_readme_success(self):
@@ -139,7 +136,7 @@ class TestREADMEExtraction(unittest.TestCase):
mock_content = Mock() mock_content = Mock()
mock_content.decoded_content = b'# React\n\nA JavaScript library' mock_content.decoded_content = b'# React\n\nA JavaScript library'
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_contents.return_value = mock_content scraper.repo.get_contents.return_value = mock_content
@@ -157,7 +154,7 @@ class TestREADMEExtraction(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
@@ -184,7 +181,7 @@ class TestREADMEExtraction(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_contents.side_effect = GithubException(404, 'Not found') scraper.repo.get_contents.side_effect = GithubException(404, 'Not found')
@@ -201,7 +198,7 @@ class TestLanguageDetection(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubScraper from skill_seekers.cli.github_scraper import GitHubScraper
self.GitHubScraper = GitHubScraper self.GitHubScraper = GitHubScraper
def test_extract_languages_success(self): def test_extract_languages_success(self):
@@ -212,7 +209,7 @@ class TestLanguageDetection(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_languages.return_value = { scraper.repo.get_languages.return_value = {
@@ -243,7 +240,7 @@ class TestLanguageDetection(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_languages.return_value = {} scraper.repo.get_languages.return_value = {}
@@ -260,7 +257,7 @@ class TestIssuesExtraction(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubScraper from skill_seekers.cli.github_scraper import GitHubScraper
self.GitHubScraper = GitHubScraper self.GitHubScraper = GitHubScraper
def test_extract_issues_success(self): def test_extract_issues_success(self):
@@ -310,7 +307,7 @@ class TestIssuesExtraction(unittest.TestCase):
mock_issue2.body = 'Feature description' mock_issue2.body = 'Feature description'
mock_issue2.pull_request = None mock_issue2.pull_request = None
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_issues.return_value = [mock_issue1, mock_issue2] scraper.repo.get_issues.return_value = [mock_issue1, mock_issue2]
@@ -361,7 +358,7 @@ class TestIssuesExtraction(unittest.TestCase):
mock_pr.title = 'Pull request' mock_pr.title = 'Pull request'
mock_pr.pull_request = Mock() # Has pull_request attribute mock_pr.pull_request = Mock() # Has pull_request attribute
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_issues.return_value = [mock_issue, mock_pr] scraper.repo.get_issues.return_value = [mock_issue, mock_pr]
@@ -399,7 +396,7 @@ class TestIssuesExtraction(unittest.TestCase):
mock_issue.pull_request = None mock_issue.pull_request = None
mock_issues.append(mock_issue) mock_issues.append(mock_issue)
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_issues.return_value = mock_issues scraper.repo.get_issues.return_value = mock_issues
@@ -417,7 +414,7 @@ class TestChangelogExtraction(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubScraper from skill_seekers.cli.github_scraper import GitHubScraper
self.GitHubScraper = GitHubScraper self.GitHubScraper = GitHubScraper
def test_extract_changelog_success(self): def test_extract_changelog_success(self):
@@ -431,7 +428,7 @@ class TestChangelogExtraction(unittest.TestCase):
mock_content = Mock() mock_content = Mock()
mock_content.decoded_content = b'# Changelog\n\n## v1.0.0\n- Initial release' mock_content.decoded_content = b'# Changelog\n\n## v1.0.0\n- Initial release'
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_contents.return_value = mock_content scraper.repo.get_contents.return_value = mock_content
@@ -449,7 +446,7 @@ class TestChangelogExtraction(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
@@ -479,7 +476,7 @@ class TestChangelogExtraction(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_contents.side_effect = GithubException(404, 'Not found') scraper.repo.get_contents.side_effect = GithubException(404, 'Not found')
@@ -496,7 +493,7 @@ class TestReleasesExtraction(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubScraper from skill_seekers.cli.github_scraper import GitHubScraper
self.GitHubScraper = GitHubScraper self.GitHubScraper = GitHubScraper
def test_extract_releases_success(self): def test_extract_releases_success(self):
@@ -532,7 +529,7 @@ class TestReleasesExtraction(unittest.TestCase):
mock_release2.tarball_url = 'https://github.com/facebook/react/archive/v18.0.0-rc.0.tar.gz' mock_release2.tarball_url = 'https://github.com/facebook/react/archive/v18.0.0-rc.0.tar.gz'
mock_release2.zipball_url = 'https://github.com/facebook/react/archive/v18.0.0-rc.0.zip' mock_release2.zipball_url = 'https://github.com/facebook/react/archive/v18.0.0-rc.0.zip'
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_releases.return_value = [mock_release1, mock_release2] scraper.repo.get_releases.return_value = [mock_release1, mock_release2]
@@ -562,7 +559,7 @@ class TestReleasesExtraction(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_releases.return_value = [] scraper.repo.get_releases.return_value = []
@@ -579,7 +576,7 @@ class TestGitHubToSkillConverter(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubToSkillConverter from skill_seekers.cli.github_scraper import GitHubToSkillConverter
self.GitHubToSkillConverter = GitHubToSkillConverter self.GitHubToSkillConverter = GitHubToSkillConverter
# Create temporary directory for test output # Create temporary directory for test output
@@ -646,7 +643,7 @@ class TestGitHubToSkillConverter(unittest.TestCase):
} }
# Override data file path # Override data file path
with patch('github_scraper.GitHubToSkillConverter.__init__') as mock_init: with patch('skill_seekers.cli.github_scraper.GitHubToSkillConverter.__init__') as mock_init:
mock_init.return_value = None mock_init.return_value = None
converter = self.GitHubToSkillConverter(config) converter = self.GitHubToSkillConverter(config)
converter.data_file = str(self.data_file) converter.data_file = str(self.data_file)
@@ -669,7 +666,7 @@ class TestGitHubToSkillConverter(unittest.TestCase):
} }
# Patch the paths to use our temp directory # Patch the paths to use our temp directory
with patch('github_scraper.GitHubToSkillConverter._load_data') as mock_load: with patch('skill_seekers.cli.github_scraper.GitHubToSkillConverter._load_data') as mock_load:
mock_load.return_value = self.mock_data mock_load.return_value = self.mock_data
converter = self.GitHubToSkillConverter(config) converter = self.GitHubToSkillConverter(config)
converter.skill_dir = str(self.output_dir / 'test_skill') converter.skill_dir = str(self.output_dir / 'test_skill')
@@ -689,7 +686,7 @@ class TestErrorHandling(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYGITHUB_AVAILABLE: if not PYGITHUB_AVAILABLE:
self.skipTest("PyGithub not installed") self.skipTest("PyGithub not installed")
from github_scraper import GitHubScraper from skill_seekers.cli.github_scraper import GitHubScraper
self.GitHubScraper = GitHubScraper self.GitHubScraper = GitHubScraper
def test_invalid_repo_name(self): def test_invalid_repo_name(self):
@@ -700,7 +697,7 @@ class TestErrorHandling(unittest.TestCase):
'github_token': None 'github_token': None
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = None scraper.repo = None
scraper.github.get_repo = Mock(side_effect=GithubException(404, 'Not found')) scraper.github.get_repo = Mock(side_effect=GithubException(404, 'Not found'))
@@ -720,7 +717,7 @@ class TestErrorHandling(unittest.TestCase):
'max_issues': 10 'max_issues': 10
} }
with patch('github_scraper.Github'): with patch('skill_seekers.cli.github_scraper.Github'):
scraper = self.GitHubScraper(config) scraper = self.GitHubScraper(config)
scraper.repo = Mock() scraper.repo = Mock()
scraper.repo.get_issues.side_effect = GithubException(403, 'Rate limit exceeded') scraper.repo.get_issues.side_effect = GithubException(403, 'Rate limit exceeded')

View File

@@ -19,9 +19,6 @@ import shutil
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, patch, MagicMock from unittest.mock import Mock, patch, MagicMock
# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent / "cli"))
try: try:
import fitz # PyMuPDF import fitz # PyMuPDF
PYMUPDF_AVAILABLE = True PYMUPDF_AVAILABLE = True
@@ -35,7 +32,7 @@ class TestPDFToSkillConverter(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYMUPDF_AVAILABLE: if not PYMUPDF_AVAILABLE:
self.skipTest("PyMuPDF not installed") self.skipTest("PyMuPDF not installed")
from pdf_scraper import PDFToSkillConverter from skill_seekers.cli.pdf_scraper import PDFToSkillConverter
self.PDFToSkillConverter = PDFToSkillConverter self.PDFToSkillConverter = PDFToSkillConverter
# Create temporary directory for test output # Create temporary directory for test output
@@ -88,7 +85,7 @@ class TestCategorization(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYMUPDF_AVAILABLE: if not PYMUPDF_AVAILABLE:
self.skipTest("PyMuPDF not installed") self.skipTest("PyMuPDF not installed")
from pdf_scraper import PDFToSkillConverter from skill_seekers.cli.pdf_scraper import PDFToSkillConverter
self.PDFToSkillConverter = PDFToSkillConverter self.PDFToSkillConverter = PDFToSkillConverter
self.temp_dir = tempfile.mkdtemp() self.temp_dir = tempfile.mkdtemp()
@@ -196,7 +193,7 @@ class TestSkillBuilding(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYMUPDF_AVAILABLE: if not PYMUPDF_AVAILABLE:
self.skipTest("PyMuPDF not installed") self.skipTest("PyMuPDF not installed")
from pdf_scraper import PDFToSkillConverter from skill_seekers.cli.pdf_scraper import PDFToSkillConverter
self.PDFToSkillConverter = PDFToSkillConverter self.PDFToSkillConverter = PDFToSkillConverter
self.temp_dir = tempfile.mkdtemp() self.temp_dir = tempfile.mkdtemp()
@@ -308,7 +305,7 @@ class TestCodeBlockHandling(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYMUPDF_AVAILABLE: if not PYMUPDF_AVAILABLE:
self.skipTest("PyMuPDF not installed") self.skipTest("PyMuPDF not installed")
from pdf_scraper import PDFToSkillConverter from skill_seekers.cli.pdf_scraper import PDFToSkillConverter
self.PDFToSkillConverter = PDFToSkillConverter self.PDFToSkillConverter = PDFToSkillConverter
self.temp_dir = tempfile.mkdtemp() self.temp_dir = tempfile.mkdtemp()
@@ -402,7 +399,7 @@ class TestImageHandling(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYMUPDF_AVAILABLE: if not PYMUPDF_AVAILABLE:
self.skipTest("PyMuPDF not installed") self.skipTest("PyMuPDF not installed")
from pdf_scraper import PDFToSkillConverter from skill_seekers.cli.pdf_scraper import PDFToSkillConverter
self.PDFToSkillConverter = PDFToSkillConverter self.PDFToSkillConverter = PDFToSkillConverter
self.temp_dir = tempfile.mkdtemp() self.temp_dir = tempfile.mkdtemp()
@@ -501,7 +498,7 @@ class TestErrorHandling(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYMUPDF_AVAILABLE: if not PYMUPDF_AVAILABLE:
self.skipTest("PyMuPDF not installed") self.skipTest("PyMuPDF not installed")
from pdf_scraper import PDFToSkillConverter from skill_seekers.cli.pdf_scraper import PDFToSkillConverter
self.PDFToSkillConverter = PDFToSkillConverter self.PDFToSkillConverter = PDFToSkillConverter
self.temp_dir = tempfile.mkdtemp() self.temp_dir = tempfile.mkdtemp()
@@ -541,7 +538,7 @@ class TestJSONWorkflow(unittest.TestCase):
def setUp(self): def setUp(self):
if not PYMUPDF_AVAILABLE: if not PYMUPDF_AVAILABLE:
self.skipTest("PyMuPDF not installed") self.skipTest("PyMuPDF not installed")
from pdf_scraper import PDFToSkillConverter from skill_seekers.cli.pdf_scraper import PDFToSkillConverter
self.PDFToSkillConverter = PDFToSkillConverter self.PDFToSkillConverter = PDFToSkillConverter
self.temp_dir = tempfile.mkdtemp() self.temp_dir = tempfile.mkdtemp()