refactor(06-02): update CLI and test imports to kb_workflow.pipeline
- Remove sys.path manipulation from kb_workflow.py - Update CLI imports to use kb_workflow.pipeline prefix - Update all test file imports and patch paths Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ class TestPipelineInput:
|
||||
|
||||
def test_schema_pipeline_input_validates_url_field(self):
|
||||
"""PipelineInput must include url field (required)"""
|
||||
from kb_pipeline.schemas import PipelineInput
|
||||
from kb_workflow.pipeline.schemas import PipelineInput
|
||||
|
||||
# Missing url
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
@@ -37,7 +37,7 @@ class TestPipelineInput:
|
||||
|
||||
def test_schema_pipeline_input_has_optional_output_dir(self):
|
||||
"""PipelineInput has optional output_dir field"""
|
||||
from kb_pipeline.schemas import PipelineInput
|
||||
from kb_workflow.pipeline.schemas import PipelineInput
|
||||
|
||||
# Without output_dir
|
||||
input_data = PipelineInput(url="https://www.bilibili.com/video/BV1xx")
|
||||
@@ -52,7 +52,7 @@ class TestPipelineInput:
|
||||
|
||||
def test_schema_pipeline_input_has_skip_completed_default(self):
|
||||
"""PipelineInput skip_completed defaults to True"""
|
||||
from kb_pipeline.schemas import PipelineInput
|
||||
from kb_workflow.pipeline.schemas import PipelineInput
|
||||
|
||||
input_data = PipelineInput(url="https://www.bilibili.com/video/BV1xx")
|
||||
assert input_data.skip_completed is True
|
||||
@@ -70,7 +70,7 @@ class TestPipelineOutput:
|
||||
|
||||
def test_schema_pipeline_output_contains_results_dict(self):
|
||||
"""PipelineOutput contains results dict"""
|
||||
from kb_pipeline.schemas import PipelineOutput
|
||||
from kb_workflow.pipeline.schemas import PipelineOutput
|
||||
|
||||
output = PipelineOutput(success=True)
|
||||
assert hasattr(output, "results")
|
||||
@@ -79,7 +79,7 @@ class TestPipelineOutput:
|
||||
|
||||
def test_schema_pipeline_output_has_success_field(self):
|
||||
"""PipelineOutput requires success field"""
|
||||
from kb_pipeline.schemas import PipelineOutput
|
||||
from kb_workflow.pipeline.schemas import PipelineOutput
|
||||
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
PipelineOutput()
|
||||
@@ -87,7 +87,7 @@ class TestPipelineOutput:
|
||||
|
||||
def test_schema_pipeline_output_has_optional_error_message(self):
|
||||
"""PipelineOutput has optional error_message field"""
|
||||
from kb_pipeline.schemas import PipelineOutput
|
||||
from kb_workflow.pipeline.schemas import PipelineOutput
|
||||
|
||||
output = PipelineOutput(success=True)
|
||||
assert output.error_message is None
|
||||
@@ -100,7 +100,7 @@ class TestPipelineOutput:
|
||||
|
||||
def test_schema_pipeline_output_has_content_dir(self):
|
||||
"""PipelineOutput has optional content_dir field"""
|
||||
from kb_pipeline.schemas import PipelineOutput
|
||||
from kb_workflow.pipeline.schemas import PipelineOutput
|
||||
|
||||
output = PipelineOutput(success=True)
|
||||
assert output.content_dir is None
|
||||
@@ -117,7 +117,7 @@ class TestPipelineConfig:
|
||||
|
||||
def test_schema_pipeline_config_has_default_steps_list(self):
|
||||
"""PipelineConfig has default steps list"""
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
config = PipelineConfig()
|
||||
assert hasattr(config, "steps")
|
||||
@@ -126,14 +126,14 @@ class TestPipelineConfig:
|
||||
|
||||
def test_schema_pipeline_config_allows_custom_steps(self):
|
||||
"""PipelineConfig allows custom steps list"""
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
custom_config = PipelineConfig(steps=["parse", "download"])
|
||||
assert custom_config.steps == ["parse", "download"]
|
||||
|
||||
def test_schema_pipeline_config_allows_custom_output_dir(self):
|
||||
"""PipelineConfig allows custom output_dir"""
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
config = PipelineConfig(output_dir=Path("/custom/output"))
|
||||
assert config.output_dir == Path("/custom/output")
|
||||
@@ -144,14 +144,14 @@ class TestPipelineConfig:
|
||||
|
||||
def test_schema_pipeline_config_has_skip_completed_default(self):
|
||||
"""PipelineConfig skip_completed defaults to True"""
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
config = PipelineConfig()
|
||||
assert config.skip_completed is True
|
||||
|
||||
def test_schema_pipeline_config_has_max_retries_default(self):
|
||||
"""PipelineConfig max_retries defaults to 3"""
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
config = PipelineConfig()
|
||||
assert config.max_retries == 3
|
||||
@@ -171,8 +171,8 @@ class TestPipelineInit:
|
||||
|
||||
def test_init_pipeline_with_processors(self):
|
||||
"""Pipeline initializes with all processors"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
mock_processor1 = MagicMock()
|
||||
mock_processor1.STEP_NAME = "parse"
|
||||
@@ -180,7 +180,7 @@ class TestPipelineInit:
|
||||
mock_processor2 = MagicMock()
|
||||
mock_processor2.STEP_NAME = "download"
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock()
|
||||
|
||||
pipeline = Pipeline(processors=[mock_processor1, mock_processor2])
|
||||
@@ -192,15 +192,15 @@ class TestPipelineInit:
|
||||
|
||||
def test_init_pipeline_validates_processor_step_name(self):
|
||||
"""Pipeline validates processor STEP_NAME matches config.steps"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
mock_processor = MagicMock()
|
||||
mock_processor.STEP_NAME = "unknown_step"
|
||||
|
||||
config = PipelineConfig(steps=["parse", "download"])
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock()
|
||||
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
@@ -210,13 +210,13 @@ class TestPipelineInit:
|
||||
|
||||
def test_init_pipeline_handles_missing_processor_gracefully(self):
|
||||
"""Pipeline handles missing processor gracefully"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
# Empty processors list should work
|
||||
config = PipelineConfig(steps=[])
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock()
|
||||
|
||||
pipeline = Pipeline(processors=[], config=config)
|
||||
@@ -228,14 +228,14 @@ class TestPipelineParseUrl:
|
||||
|
||||
def test_parse_url_creates_correct_content_directory(self):
|
||||
"""Pipeline._get_content_dir creates correct content directory"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_pipeline.link_parser import ParsedLink
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.link_parser import ParsedLink
|
||||
import tempfile
|
||||
|
||||
mock_processor = MagicMock()
|
||||
mock_processor.STEP_NAME = "parse"
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock()
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
@@ -258,12 +258,12 @@ class TestPipelineParseUrl:
|
||||
|
||||
def test_parse_url_returns_none_for_empty_url(self):
|
||||
"""Pipeline._parse_url returns None for empty URL"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
|
||||
mock_processor = MagicMock()
|
||||
mock_processor.STEP_NAME = "parse"
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock()
|
||||
|
||||
pipeline = Pipeline(processors=[mock_processor])
|
||||
@@ -273,12 +273,12 @@ class TestPipelineParseUrl:
|
||||
|
||||
def test_parse_url_returns_none_for_invalid_url(self):
|
||||
"""Pipeline._parse_url returns None for unrecognized URL"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
|
||||
mock_processor = MagicMock()
|
||||
mock_processor.STEP_NAME = "parse"
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock()
|
||||
|
||||
pipeline = Pipeline(processors=[mock_processor])
|
||||
@@ -288,12 +288,12 @@ class TestPipelineParseUrl:
|
||||
|
||||
def test_parse_url_parses_bilibili_url(self):
|
||||
"""Pipeline._parse_url correctly parses Bilibili URL"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
|
||||
mock_processor = MagicMock()
|
||||
mock_processor.STEP_NAME = "parse"
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock()
|
||||
|
||||
pipeline = Pipeline(processors=[mock_processor])
|
||||
@@ -373,8 +373,8 @@ class TestPipelineArchiveStep:
|
||||
@pytest.mark.asyncio
|
||||
async def test_pipeline_includes_archive_step(self, mock_processors_with_archive, tmp_path):
|
||||
"""Test that pipeline includes archive as final step"""
|
||||
from kb_pipeline.pipeline import Pipeline
|
||||
from kb_pipeline.schemas import PipelineConfig
|
||||
from kb_workflow.pipeline.pipeline import Pipeline
|
||||
from kb_workflow.pipeline.schemas import PipelineConfig
|
||||
|
||||
config = PipelineConfig(
|
||||
steps=["parse", "download", "asr", "analyze", "archive"],
|
||||
@@ -382,7 +382,7 @@ class TestPipelineArchiveStep:
|
||||
skip_completed=False
|
||||
)
|
||||
|
||||
with patch("kb_pipeline.pipeline.get_settings") as mock_settings:
|
||||
with patch("kb_workflow.pipeline.pipeline.get_settings") as mock_settings:
|
||||
mock_settings.return_value = MagicMock(intermediate_path=str(tmp_path))
|
||||
|
||||
pipeline = Pipeline(
|
||||
@@ -395,7 +395,7 @@ class TestPipelineArchiveStep:
|
||||
with patch.object(pipeline, '_parse_url') as mock_parse, \
|
||||
patch.object(pipeline, '_get_content_dir') as mock_dir:
|
||||
|
||||
from kb_pipeline.link_parser import ParsedLink
|
||||
from kb_workflow.pipeline.link_parser import ParsedLink
|
||||
mock_parse.return_value = ParsedLink(
|
||||
platform="bilibili",
|
||||
content_type="video",
|
||||
@@ -419,8 +419,8 @@ class TestArchivePlatformDirectory:
|
||||
@pytest.mark.asyncio
|
||||
async def test_archive_uses_platform_directory(self, tmp_path):
|
||||
"""Test that archive files go to {archive_path}/{platform}/ directory"""
|
||||
from kb_pipeline.processors.archive import ArchiveProcessor
|
||||
from kb_pipeline.schemas import ArchiveInput
|
||||
from kb_workflow.pipeline.processors.archive import ArchiveProcessor
|
||||
from kb_workflow.pipeline.schemas import ArchiveInput
|
||||
|
||||
# Setup
|
||||
archive_dir = tmp_path / "archive"
|
||||
@@ -430,7 +430,7 @@ class TestArchivePlatformDirectory:
|
||||
analysis_file.write_text("# Test")
|
||||
|
||||
# Mock settings - patch at base module level where get_settings is called in __init__
|
||||
with patch('kb_pipeline.processors.base.get_settings') as mock_get_settings:
|
||||
with patch('kb_workflow.pipeline.processors.base.get_settings') as mock_get_settings:
|
||||
mock_settings = MagicMock()
|
||||
mock_settings.archive_path = str(archive_dir)
|
||||
mock_get_settings.return_value = mock_settings
|
||||
@@ -461,8 +461,8 @@ class TestArchiveNoDateSubdirectories:
|
||||
@pytest.mark.asyncio
|
||||
async def test_archive_no_date_subdirectories(self, tmp_path):
|
||||
"""Test that archive does not create date-based subdirectories"""
|
||||
from kb_pipeline.processors.archive import ArchiveProcessor
|
||||
from kb_pipeline.schemas import ArchiveInput
|
||||
from kb_workflow.pipeline.processors.archive import ArchiveProcessor
|
||||
from kb_workflow.pipeline.schemas import ArchiveInput
|
||||
|
||||
archive_dir = tmp_path / "archive"
|
||||
content_dir = tmp_path / "intermediate" / "bilibili_BV1test"
|
||||
@@ -470,7 +470,7 @@ class TestArchiveNoDateSubdirectories:
|
||||
analysis_file = content_dir / "analysis.md"
|
||||
analysis_file.write_text("# Test")
|
||||
|
||||
with patch('kb_pipeline.processors.base.get_settings') as mock_get_settings:
|
||||
with patch('kb_workflow.pipeline.processors.base.get_settings') as mock_get_settings:
|
||||
mock_settings = MagicMock()
|
||||
mock_settings.archive_path = str(archive_dir)
|
||||
mock_get_settings.return_value = mock_settings
|
||||
|
||||
Reference in New Issue
Block a user