diff --git a/src/poly/resources/documents.py b/src/poly/resources/documents.py index cb7b9c25..a522d5ae 100644 --- a/src/poly/resources/documents.py +++ b/src/poly/resources/documents.py @@ -14,6 +14,8 @@ ) from poly.resources.resource import Resource, register_resource +PLATFORM_CONTEXT_FILE = "CONTEXT.MD" + @register_resource("documents") @dataclass @@ -23,10 +25,6 @@ class Document(Resource): path: str contents: str - def __post_init__(self) -> None: - """Normalize path to uppercase to match platform convention.""" - self.path = self.path.upper() - @cached_property def file_path(self) -> str: """Get the file path for the Document resource.""" @@ -49,7 +47,10 @@ def from_pretty(cls, contents: str, **kwargs) -> str: def validate(self, **kwargs) -> None: """Validate the resource.""" - pass + if self.path.upper() == PLATFORM_CONTEXT_FILE and self.path != PLATFORM_CONTEXT_FILE: + raise ValueError( + f"Document path must be {PLATFORM_CONTEXT_FILE} (case-sensitive) for the platform context file." + ) @classmethod def read_local_resource( @@ -118,7 +119,7 @@ def discover_resources(base_path: str) -> list[str]: for file_name in os.listdir(context_path): if not file_name.upper().endswith(".MD"): continue - file_path = os.path.join(context_path, file_name.upper()) + file_path = os.path.join(context_path, file_name) file_paths.append(file_path) return file_paths @@ -134,7 +135,7 @@ def from_projection(cls, projection: dict) -> dict[str, "Document"]: if "content" not in document_data: continue path = document_data.get("path", "") or "" - name = path.removesuffix(".md") + name = path.removesuffix(".md").removesuffix(".MD") documents[document_id] = Document( resource_id=document_id, name=name, diff --git a/src/poly/tests/project_test.py b/src/poly/tests/project_test.py index f3d250a3..e4ff8507 100644 --- a/src/poly/tests/project_test.py +++ b/src/poly/tests/project_test.py @@ -208,9 +208,8 @@ def test_document_round_trip(self): restored = Document(**serialized) self.assertEqual(restored.resource_id, "test.md") self.assertEqual(restored.name, "test") - self.assertEqual(restored.path, "TEST.MD") - self.assertEqual(restored.contents, "hello world\n") - self.assertEqual(restored.file_path, os.path.join("context", "TEST.MD")) + self.assertEqual(restored.path, "test.md") + self.assertEqual(restored.file_path, os.path.join("context", "test.md")) self.assertEqual(restored.compute_hash(), doc.compute_hash()) def test_flow_step_round_trip_excludes_sub_resource_internals(self): @@ -429,11 +428,12 @@ def test_discover_local_resources(self): ) # Find Documents - self.assertEqual(len(local_resources[Document]), 1) + self.assertEqual(len(local_resources[Document]), 2) self.assertCountEqual( local_resources[Document], [ - os.path.join(TEST_DIR, "context", "TEST_DOCUMENT.MD"), + os.path.join(TEST_DIR, "context", "test_document.md"), + os.path.join(TEST_DIR, "context", "CONTEXT.MD"), ], ) diff --git a/src/poly/tests/resources_test.py b/src/poly/tests/resources_test.py index 1bb94462..cc612c0f 100644 --- a/src/poly/tests/resources_test.py +++ b/src/poly/tests/resources_test.py @@ -8620,7 +8620,7 @@ class DocumentTests(unittest.TestCase): def test_file_path(self): doc = Document(resource_id="test.md", name="test", path="test.md", contents="hello") - self.assertEqual(doc.file_path, os.path.join("context", "TEST.MD")) + self.assertEqual(doc.file_path, os.path.join("context", "test.md")) def test_raw(self): doc = Document(resource_id="test.md", name="test", path="test.md", contents="some content") @@ -8648,7 +8648,7 @@ def test_read_local_resource(self): ) self.assertEqual(doc.resource_id, "doc.md") self.assertEqual(doc.name, "doc") - self.assertEqual(doc.path, "DOC.MD") + self.assertEqual(doc.path, "doc.md") self.assertEqual(doc.contents, "file contents\n") def test_save_and_read_round_trip(self): @@ -8663,12 +8663,12 @@ def test_save_and_read_round_trip(self): ) doc.save(tmpdir) - file_path = os.path.join(tmpdir, "context", "ROUND_TRIP.MD") + file_path = os.path.join(tmpdir, "context", "round_trip.md") self.assertTrue(os.path.exists(file_path)) restored = Document.read_local_resource( file_path=file_path, - resource_id="ROUND_TRIP.MD", + resource_id="round_trip.md", resource_name="round_trip", ) self.assertEqual(restored.contents, doc.contents) @@ -8691,8 +8691,8 @@ def test_discover_resources(self): self.assertCountEqual( discovered, [ - os.path.join(context_dir, "DOC1.MD"), - os.path.join(context_dir, "DOC2.MD"), + os.path.join(context_dir, "doc1.md"), + os.path.join(context_dir, "doc2.md"), ], ) @@ -8703,16 +8703,25 @@ def test_discover_resources_no_context_dir(self): discovered = Document.discover_resources(tmpdir) self.assertEqual(discovered, []) - def test_path_normalized_to_uppercase(self): - """Documents with different-case paths produce the same normalized path.""" + def test_path_case_preserved(self): + """Document paths are stored as given, not forced to a fixed case.""" doc_lower = Document(resource_id="ctx.md", name="ctx", path="context.md", contents="hello") - doc_upper = Document(resource_id="ctx.md", name="ctx", path="CONTEXT.MD", contents="hello") doc_mixed = Document(resource_id="ctx.md", name="ctx", path="Context.Md", contents="hello") - self.assertEqual(doc_lower.path, "CONTEXT.MD") - self.assertEqual(doc_upper.path, "CONTEXT.MD") - self.assertEqual(doc_mixed.path, "CONTEXT.MD") - self.assertEqual(doc_lower.file_path, doc_upper.file_path) - self.assertEqual(doc_lower.file_path, doc_mixed.file_path) + self.assertEqual(doc_lower.path, "context.md") + self.assertEqual(doc_mixed.path, "Context.Md") + + def test_validate_allows_non_context_paths_in_any_case(self): + doc = Document(resource_id="notes.md", name="notes", path="Notes.Md", contents="hello") + doc.validate() + + def test_validate_allows_exact_case_platform_context_file(self): + doc = Document(resource_id="ctx.md", name="ctx", path="CONTEXT.MD", contents="hello") + doc.validate() + + def test_validate_rejects_wrong_case_platform_context_file(self): + doc = Document(resource_id="ctx.md", name="ctx", path="context.md", contents="hello") + with self.assertRaises(ValueError): + doc.validate() class DocumentFromProjection(unittest.TestCase): diff --git a/src/poly/tests/test_projects/test_project/context/CONTEXT.MD b/src/poly/tests/test_projects/test_project/context/CONTEXT.MD new file mode 100644 index 00000000..396eefeb --- /dev/null +++ b/src/poly/tests/test_projects/test_project/context/CONTEXT.MD @@ -0,0 +1 @@ +This is platform context file. diff --git a/src/poly/tests/test_projects/test_project/context/TEST_DOCUMENT.MD b/src/poly/tests/test_projects/test_project/context/test_document.md similarity index 100% rename from src/poly/tests/test_projects/test_project/context/TEST_DOCUMENT.MD rename to src/poly/tests/test_projects/test_project/context/test_document.md diff --git a/src/poly/tests/test_projects/test_project/test_project.json b/src/poly/tests/test_projects/test_project/test_project.json index 25f02077..7941d12b 100644 --- a/src/poly/tests/test_projects/test_project/test_project.json +++ b/src/poly/tests/test_projects/test_project/test_project.json @@ -1304,6 +1304,12 @@ "name": "test_document", "path": "test_document.md", "contents": "This is a test document.\nIt has multiple lines.\n" + }, + "CONTEXT.MD": { + "resource_id": "CONTEXT.MD", + "name": "CONTEXT", + "path": "CONTEXT.MD", + "contents": "This is platform context file.\n" } } }, diff --git a/uv.lock b/uv.lock index b5864a67..ecb1a2d7 100644 --- a/uv.lock +++ b/uv.lock @@ -359,7 +359,7 @@ wheels = [ [[package]] name = "polyai-adk" -version = "0.36.3" +version = "0.44.3" source = { editable = "." } dependencies = [ { name = "argcomplete" },