Skip to content

Commit 91095f5

Browse files
Fix/ut concept library (Pipelex#145)
1 parent c43ad68 commit 91095f5

6 files changed

Lines changed: 207 additions & 3 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ dependencies = [
2424
"instructor>=1.8.3",
2525
"jinja2>=3.1.4",
2626
"json2html>=1.3.0",
27-
"kajson @ git+https://github.com/Pipelex/kajson.git@refactor/Proper-Singleton",
27+
"kajson==0.3.0",
2828
"markdown>=3.6",
2929
"networkx>=3.4.2",
3030
"openai>=1.60.1",

tests/conftest.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import pipelex.pipelex
1010
from pipelex import log
1111
from pipelex.config import get_config
12+
from pipelex.core.concept_provider_abstract import ConceptProviderAbstract
13+
from pipelex.hub import get_concept_provider
1214
from tests.cases.registry import Fruit
1315

1416
pytest_plugins = [
@@ -66,3 +68,9 @@ def cherry() -> Fruit:
6668
def blueberry() -> Fruit:
6769
"""Blueberry fruit fixture."""
6870
return Fruit(name="blueberry", color="blue")
71+
72+
73+
@pytest.fixture(scope="module")
74+
def concept_provider() -> ConceptProviderAbstract:
75+
"""Concept provider fixture for testing concept compatibility."""
76+
return get_concept_provider()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from typing import Dict, List, Optional
2+
3+
from pydantic import Field
4+
5+
from pipelex.core.stuff_content import StructuredContent
6+
7+
8+
class FundamentalsDoc(StructuredContent):
9+
project_overview: Optional[str] = Field(
10+
None,
11+
description="Mission, key features, architecture diagram, demo links",
12+
)
13+
core_concepts: Optional[Dict[str, str]] = Field(
14+
None,
15+
description=(
16+
"Names and definitions for project-specific terms, acronyms, data model names, background knowledge, business rules, domain entities"
17+
),
18+
)
19+
repository_map: Optional[str] = Field(
20+
None,
21+
description="Directory layout explanation and purpose of each folder",
22+
)
23+
24+
25+
class DocumentationConcept(StructuredContent):
26+
"""A specialized documentation concept that extends FundamentalsDoc."""
27+
28+
title: str = Field(..., description="Title of the documentation")
29+
sections: List[str] = Field(default_factory=list, description="List of section names")
30+
last_updated: Optional[str] = Field(None, description="Last update timestamp")
31+
32+
33+
class MultiMediaConcept(StructuredContent):
34+
"""A concept that combines text and images."""
35+
36+
text_content: str = Field(..., description="The text content")
37+
image_urls: List[str] = Field(default_factory=list, description="List of image URLs")
38+
caption: Optional[str] = Field(None, description="Optional caption for the content")
39+
40+
41+
class IndependentConcept(StructuredContent):
42+
"""An independent concept with its own structure."""
43+
44+
unique_field: str = Field(..., description="A unique field for this concept")
45+
metadata: Dict[str, str] = Field(default_factory=dict, description="Metadata dictionary")
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
domain = "concept_library_tests"
2+
3+
[concept]
4+
# Simple concept with no structure - should default to Text
5+
SimpleTextConcept = "A simple concept that should default to Text"
6+
7+
# Concept with explicit structure class
8+
FundamentalsDoc = "A comprehensive overview of the fundamental concepts and principles of software engineering."
9+
10+
# Concept that explicitly refines Text
11+
[concept.ExplicitTextConcept]
12+
Concept = "A concept that explicitly refines Text"
13+
refines = ["Text"]
14+
15+
# Concept that refines Image
16+
[concept.ImageBasedConcept]
17+
Concept = "A concept based on images"
18+
refines = ["Image"]
19+
20+
# Concept that refines FundamentalsDoc
21+
[concept.DocumentationConcept]
22+
Concept = "A specialized documentation concept"
23+
structure = "DocumentationConcept"
24+
refines = ["FundamentalsDoc"]
25+
26+
# Concept that refines both Text and Image (multiple inheritance)
27+
[concept.MultiMediaConcept]
28+
Concept = "A concept that combines text and images"
29+
structure = "MultiMediaConcept"
30+
refines = ["Text", "Image"]
31+
32+
# Concept with custom structure that doesn't refine anything
33+
[concept.IndependentConcept]
34+
Concept = "An independent concept with custom structure"
35+
structure = "IndependentConcept"
36+
37+
# Concept that refines a non-native concept
38+
[concept.SpecializedDoc]
39+
Concept = "A specialized document that builds on FundamentalsDoc"
40+
refines = ["FundamentalsDoc"]
41+
42+
# Chain of inheritance: Text -> ExplicitTextConcept -> DerivedTextConcept
43+
[concept.DerivedTextConcept]
44+
Concept = "A concept derived from ExplicitTextConcept"
45+
refines = ["ExplicitTextConcept"]
46+

tests/unit/pipelex/core/test_concept_library.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from pipelex.core.concept import Concept
22
from pipelex.core.concept_native import NativeConcept
3+
from pipelex.core.concept_provider_abstract import ConceptProviderAbstract
34

45

56
class Testget_concept_providerIsNativeConcept:
@@ -128,3 +129,103 @@ def test_is_native_concept_common_examples(self):
128129

129130
# And they should also work with the explicit "native." prefix
130131
assert Concept.is_native_concept(f"native.{concept_name}") is True, f"'native.{concept_name}' should also be recognized as native concept"
132+
133+
134+
class TestConceptLibraryCompatibility:
135+
"""Test ConceptLibrary compatibility methods."""
136+
137+
def test_is_compatible_by_concept_code_simple_text_concept_vs_text(self, concept_provider: ConceptProviderAbstract):
138+
"""Test that SimpleTextConcept (no structure) is compatible with native Text."""
139+
# Test: SimpleTextConcept should be compatible with native Text (defaults to Text)
140+
result = concept_provider.is_compatible_by_concept_code(
141+
tested_concept_code="concept_library_tests.SimpleTextConcept", wanted_concept_code="native.Text"
142+
)
143+
assert result is True, "SimpleTextConcept should be compatible with native Text"
144+
145+
def test_is_compatible_by_concept_code_fundamentals_doc_vs_text(self, concept_provider: ConceptProviderAbstract):
146+
"""Test that FundamentalsDoc (custom structure) is not compatible with native Text."""
147+
# Test: FundamentalsDoc should NOT be compatible with native Text (has custom structure)
148+
result = concept_provider.is_compatible_by_concept_code(
149+
tested_concept_code="concept_library_tests.FundamentalsDoc", wanted_concept_code="native.Text"
150+
)
151+
assert result is False, "FundamentalsDoc should not be compatible with native Text"
152+
153+
def test_is_compatible_by_concept_code_explicit_text_concept_vs_text(self, concept_provider: ConceptProviderAbstract):
154+
"""Test that ExplicitTextConcept (explicitly refines Text) is compatible with native Text."""
155+
# Test: ExplicitTextConcept should be compatible with native Text
156+
result = concept_provider.is_compatible_by_concept_code(
157+
tested_concept_code="concept_library_tests.ExplicitTextConcept", wanted_concept_code="native.Text"
158+
)
159+
assert result is True, "ExplicitTextConcept should be compatible with native Text"
160+
161+
def test_is_compatible_by_concept_code_image_based_concept_vs_image(self, concept_provider: ConceptProviderAbstract):
162+
"""Test that ImageBasedConcept is compatible with native Image."""
163+
# Test: ImageBasedConcept should be compatible with native Image
164+
result = concept_provider.is_compatible_by_concept_code(
165+
tested_concept_code="concept_library_tests.ImageBasedConcept", wanted_concept_code="native.Image"
166+
)
167+
assert result is True, "ImageBasedConcept should be compatible with native Image"
168+
169+
def test_is_compatible_by_concept_code_image_based_concept_vs_text(self, concept_provider: ConceptProviderAbstract):
170+
"""Test that ImageBasedConcept is not compatible with native Text."""
171+
# Test: ImageBasedConcept should NOT be compatible with native Text
172+
result = concept_provider.is_compatible_by_concept_code(
173+
tested_concept_code="concept_library_tests.ImageBasedConcept", wanted_concept_code="native.Text"
174+
)
175+
assert result is False, "ImageBasedConcept should not be compatible with native Text"
176+
177+
def test_is_compatible_by_concept_code_documentation_concept_vs_fundamentals_doc(self, concept_provider: ConceptProviderAbstract):
178+
"""Test that DocumentationConcept is compatible with FundamentalsDoc."""
179+
# Test: DocumentationConcept should be compatible with FundamentalsDoc
180+
result = concept_provider.is_compatible_by_concept_code(
181+
tested_concept_code="concept_library_tests.DocumentationConcept", wanted_concept_code="concept_library_tests.FundamentalsDoc"
182+
)
183+
assert result is True, "DocumentationConcept should be compatible with FundamentalsDoc"
184+
185+
def test_is_compatible_by_concept_code_specialized_doc_vs_fundamentals_doc(self, concept_provider: ConceptProviderAbstract):
186+
"""Test that SpecializedDoc is compatible with FundamentalsDoc."""
187+
# Test: SpecializedDoc should be compatible with FundamentalsDoc
188+
result = concept_provider.is_compatible_by_concept_code(
189+
tested_concept_code="concept_library_tests.SpecializedDoc", wanted_concept_code="concept_library_tests.FundamentalsDoc"
190+
)
191+
assert result is True, "SpecializedDoc should be compatible with FundamentalsDoc"
192+
193+
def test_is_compatible_by_concept_code_multimedia_concept_vs_text(self, concept_provider: ConceptProviderAbstract):
194+
"""Test that MultiMediaConcept is compatible with Text (multiple inheritance)."""
195+
# Test: MultiMediaConcept should be compatible with Text
196+
result = concept_provider.is_compatible_by_concept_code(
197+
tested_concept_code="concept_library_tests.MultiMediaConcept", wanted_concept_code="native.Text"
198+
)
199+
assert result is True, "MultiMediaConcept should be compatible with Text"
200+
201+
def test_is_compatible_by_concept_code_multimedia_concept_vs_image(self, concept_provider: ConceptProviderAbstract):
202+
"""Test that MultiMediaConcept is compatible with Image (multiple inheritance)."""
203+
# Test: MultiMediaConcept should be compatible with Image
204+
result = concept_provider.is_compatible_by_concept_code(
205+
tested_concept_code="concept_library_tests.MultiMediaConcept", wanted_concept_code="native.Image"
206+
)
207+
assert result is True, "MultiMediaConcept should be compatible with Image"
208+
209+
def test_is_compatible_by_concept_code_independent_concept_vs_text(self, concept_provider: ConceptProviderAbstract):
210+
"""Test that IndependentConcept is not compatible with Text."""
211+
# Test: IndependentConcept should NOT be compatible with Text (no refines)
212+
result = concept_provider.is_compatible_by_concept_code(
213+
tested_concept_code="concept_library_tests.IndependentConcept", wanted_concept_code="native.Text"
214+
)
215+
assert result is False, "IndependentConcept should not be compatible with Text"
216+
217+
def test_is_compatible_by_concept_code_derived_text_concept_vs_text(self, concept_provider: ConceptProviderAbstract):
218+
"""Test that DerivedTextConcept is compatible with Text (inheritance chain)."""
219+
# Test: DerivedTextConcept should be compatible with Text (through ExplicitTextConcept)
220+
result = concept_provider.is_compatible_by_concept_code(
221+
tested_concept_code="concept_library_tests.DerivedTextConcept", wanted_concept_code="native.Text"
222+
)
223+
assert result is True, "DerivedTextConcept should be compatible with Text through inheritance chain"
224+
225+
def test_is_compatible_by_concept_code_derived_text_concept_vs_explicit_text(self, concept_provider: ConceptProviderAbstract):
226+
"""Test that DerivedTextConcept is compatible with ExplicitTextConcept (direct inheritance)."""
227+
# Test: DerivedTextConcept should be compatible with ExplicitTextConcept
228+
result = concept_provider.is_compatible_by_concept_code(
229+
tested_concept_code="concept_library_tests.DerivedTextConcept", wanted_concept_code="concept_library_tests.ExplicitTextConcept"
230+
)
231+
assert result is True, "DerivedTextConcept should be compatible with ExplicitTextConcept"

uv.lock

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)