|
4 | 4 | import pytest |
5 | 5 | import yaml |
6 | 6 |
|
7 | | -from clarifai.runners.pipelines import ComputeInfo, Pipeline, step, step_ref |
| 7 | +from clarifai.runners.pipelines import ( |
| 8 | + ComputeInfo, |
| 9 | + Pipeline, |
| 10 | + load_pipeline_from_file, |
| 11 | + step, |
| 12 | + step_ref, |
| 13 | +) |
8 | 14 | from clarifai.runners.utils.pipeline_validation import PipelineConfigValidator |
9 | 15 |
|
10 | 16 |
|
11 | 17 | def normalize_text(value: str) -> str: |
12 | | - return ' '.join(value.strip().split()) |
| 18 | + import importlib.util |
| 19 | + |
| 20 | + module_path = Path(__file__).with_name('sample_module.py') |
| 21 | + spec = importlib.util.spec_from_file_location('sample_module', module_path) |
| 22 | + if spec is None or spec.loader is None: |
| 23 | + raise RuntimeError(f'Could not load helper module from {module_path}') |
| 24 | + |
| 25 | + module = importlib.util.module_from_spec(spec) |
| 26 | + spec.loader.exec_module(module) |
| 27 | + return module.clean_text(value) |
13 | 28 |
|
14 | 29 |
|
15 | 30 | @step( |
16 | 31 | id='prepare-text', |
17 | 32 | requirements=['transformers>=4.0'], |
| 33 | + assets=['../assets/sample.txt', '../assets/sample_texts', './sample_module.py'], |
18 | 34 | compute=ComputeInfo(cpu_limit='500m', cpu_memory='500Mi'), |
19 | 35 | ) |
20 | 36 | def prepare_text(input_text: str) -> str: |
@@ -104,19 +120,65 @@ def test_pipeline_generate_writes_helper_functions_and_expected_files(tmp_path: |
104 | 120 | assert (tmp_path / 'prepare-text' / 'requirements.txt').exists() |
105 | 121 | step_script = tmp_path / 'prepare-text' / '1' / 'pipeline_step.py' |
106 | 122 | assert step_script.exists() |
| 123 | + assert (tmp_path / 'prepare-text' / '1' / 'sample.txt').exists() |
| 124 | + assert (tmp_path / 'prepare-text' / '1' / 'sample_module.py').exists() |
| 125 | + assert (tmp_path / 'prepare-text' / '1' / 'sample_texts' / 'sample1.txt').exists() |
107 | 126 |
|
108 | 127 | step_script_content = step_script.read_text(encoding='utf-8') |
109 | 128 | requirements_content = (tmp_path / 'prepare-text' / 'requirements.txt').read_text( |
110 | 129 | encoding='utf-8' |
111 | 130 | ) |
112 | 131 |
|
113 | 132 | assert 'def normalize_text(value: str) -> str:' in step_script_content |
| 133 | + assert "with_name('sample_module.py')" in step_script_content |
114 | 134 | assert '@step' not in step_script_content |
115 | 135 | assert 'transformers>=4.0' in requirements_content |
116 | 136 | assert not (tmp_path / 'summarize').exists() |
117 | 137 | assert not (tmp_path / 'classify-sentiment').exists() |
118 | 138 |
|
119 | 139 |
|
| 140 | +def test_pipeline_generate_raises_for_missing_step_asset(tmp_path: Path): |
| 141 | + @step(id='missing-asset', assets=['./does-not-exist.txt']) |
| 142 | + def missing_asset_step(input_text: str) -> str: |
| 143 | + return input_text |
| 144 | + |
| 145 | + with Pipeline(id='asset-pipeline', user_id='me', app_id='my-app') as pipeline: |
| 146 | + raw_text = pipeline.input('input_text') |
| 147 | + missing_asset_step(input_text=raw_text) |
| 148 | + |
| 149 | + with pytest.raises(ValueError, match='asset path does not exist'): |
| 150 | + pipeline.generate(str(tmp_path)) |
| 151 | + |
| 152 | + |
| 153 | +def test_pipeline_generate_raises_for_duplicate_asset_basename(tmp_path: Path): |
| 154 | + dir_a = tmp_path / 'a' |
| 155 | + dir_b = tmp_path / 'b' |
| 156 | + dir_a.mkdir() |
| 157 | + dir_b.mkdir() |
| 158 | + (dir_a / 'helper.py').write_text('# helper a') |
| 159 | + (dir_b / 'helper.py').write_text('# helper b') |
| 160 | + |
| 161 | + @step(id='dup-asset', assets=[str(dir_a / 'helper.py'), str(dir_b / 'helper.py')]) |
| 162 | + def dup_asset_step(input_text: str) -> str: |
| 163 | + return input_text |
| 164 | + |
| 165 | + with Pipeline(id='dup-pipeline', user_id='me', app_id='my-app') as pipeline: |
| 166 | + raw_text = pipeline.input('input_text') |
| 167 | + dup_asset_step(input_text=raw_text) |
| 168 | + |
| 169 | + with pytest.raises(ValueError, match='duplicate asset basename'): |
| 170 | + pipeline.generate(str(tmp_path / 'generated')) |
| 171 | + |
| 172 | + |
| 173 | +def test_pipeline_generate_raises_for_reserved_step_asset_name(tmp_path: Path): |
| 174 | + pipeline = load_pipeline_from_file( |
| 175 | + str(Path(__file__).with_name('invalid_reserved_asset_pipeline.py')) |
| 176 | + ) |
| 177 | + |
| 178 | + with pytest.raises(ValueError, match='asset basename is reserved'): |
| 179 | + pipeline.generate(str(tmp_path / 'generated')) |
| 180 | + |
| 181 | + |
120 | 182 | def test_validator_collects_only_managed_steps_without_versions(): |
121 | 183 | pipeline = build_pipeline() |
122 | 184 |
|
|
0 commit comments