pixie-prompts 0.0.0__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1453 +0,0 @@
1
- """Comprehensive unit tests for pixie.prompts.storage module."""
2
-
3
- import json
4
- import os
5
- import tempfile
6
- import pytest
7
- from types import NoneType
8
- from typing import Dict
9
-
10
- from pixie.prompts.prompt import BaseUntypedPrompt, BasePrompt, _prompt_registry
11
- from pixie.prompts.storage import _FilePromptStorage
12
-
13
-
14
- class TestFilePromptStorage:
15
- """Tests for FilePromptStorage class."""
16
-
17
- @pytest.fixture(autouse=True)
18
- def clear_prompt_registry(self):
19
- """Clear the global prompt registry before each test."""
20
- _prompt_registry.clear()
21
-
22
- @pytest.fixture(autouse=True)
23
- def reset_storage_instance(self):
24
- """Reset the global storage instance before each test."""
25
- import pixie.prompts.storage as storage_module
26
-
27
- storage_module._storage_instance = None
28
- yield
29
- storage_module._storage_instance = None
30
-
31
- @pytest.fixture
32
- def temp_dir(self):
33
- """Create a temporary directory for testing."""
34
- with tempfile.TemporaryDirectory() as tmpdir:
35
- yield tmpdir
36
-
37
- @pytest.fixture
38
- def sample_prompt_data(self) -> Dict[str, Dict]:
39
- """Sample prompt data for testing."""
40
- return {
41
- "prompt1": {
42
- "versions": {"v1": "Hello {name}", "v2": "Hi {name}"},
43
- "defaultVersionId": "v1",
44
- "variablesSchema": {"type": "object", "properties": {}},
45
- },
46
- "prompt2": {
47
- "versions": {"default": "Goodbye {name}"},
48
- "defaultVersionId": "default",
49
- "variablesSchema": {"type": "object", "properties": {}},
50
- },
51
- }
52
-
53
- def create_sample_files(self, temp_dir: str, sample_data: Dict[str, Dict]):
54
- """Create sample JSON files in the temp directory."""
55
- for prompt_id, data in sample_data.items():
56
- filepath = os.path.join(temp_dir, f"{prompt_id}.json")
57
- with open(filepath, "w") as f:
58
- json.dump(data, f)
59
-
60
- def test_init_creates_directory_if_not_exists(self, temp_dir: str):
61
- """Test that __init__ creates the directory if it doesn't exist."""
62
- subdir = os.path.join(temp_dir, "storage")
63
- assert not os.path.exists(subdir)
64
-
65
- storage = _FilePromptStorage(subdir)
66
- assert os.path.exists(subdir)
67
- assert isinstance(storage._prompts, dict)
68
- assert len(storage._prompts) == 0
69
-
70
- @pytest.mark.asyncio
71
- async def test_init_loads_existing_files(
72
- self, temp_dir: str, sample_prompt_data: Dict[str, Dict]
73
- ):
74
- """Test that __init__ loads existing JSON files into memory."""
75
- self.create_sample_files(temp_dir, sample_prompt_data)
76
-
77
- storage = _FilePromptStorage(temp_dir)
78
-
79
- assert len(storage._prompts) == 2
80
- assert "prompt1" in storage._prompts
81
- assert "prompt2" in storage._prompts
82
-
83
- prompt1 = storage._prompts["prompt1"]
84
- assert isinstance(prompt1, BaseUntypedPrompt)
85
- assert prompt1.id == "prompt1"
86
- assert prompt1.get_versions() == sample_prompt_data["prompt1"]["versions"]
87
- assert (
88
- prompt1.get_default_version_id()
89
- == sample_prompt_data["prompt1"]["defaultVersionId"]
90
- )
91
-
92
- prompt2 = storage._prompts["prompt2"]
93
- assert prompt2.id == "prompt2"
94
- assert prompt2.get_versions() == sample_prompt_data["prompt2"]["versions"]
95
- assert (
96
- prompt2.get_default_version_id()
97
- == sample_prompt_data["prompt2"]["defaultVersionId"]
98
- )
99
-
100
- def test_init_handles_empty_directory(self, temp_dir: str):
101
- """Test that __init__ handles an empty directory gracefully."""
102
- storage = _FilePromptStorage(temp_dir)
103
- assert len(storage._prompts) == 0
104
-
105
- def test_init_skips_non_json_files(self, temp_dir: str):
106
- """Test that __init__ skips files that don't end with .json."""
107
- # Create a JSON file and a non-JSON file
108
- json_path = os.path.join(temp_dir, "prompt1.json")
109
- with open(json_path, "w") as f:
110
- json.dump(
111
- {
112
- "versions": {"default": "test"},
113
- "defaultVersionId": "default",
114
- "variablesSchema": {"type": "object", "properties": {}},
115
- },
116
- f,
117
- )
118
-
119
- txt_path = os.path.join(temp_dir, "readme.txt")
120
- with open(txt_path, "w") as f:
121
- f.write("This is not JSON")
122
-
123
- storage = _FilePromptStorage(temp_dir)
124
- assert len(storage._prompts) == 1
125
- assert "prompt1" in storage._prompts
126
-
127
- def test_init_handles_invalid_json(self, temp_dir: str):
128
- """Test that __init__ raises an exception for invalid JSON."""
129
- invalid_path = os.path.join(temp_dir, "invalid.json")
130
- with open(invalid_path, "w") as f:
131
- f.write("invalid json content")
132
-
133
- with pytest.raises(json.JSONDecodeError):
134
- _FilePromptStorage(temp_dir)
135
-
136
- def test_init_handles_missing_versions(self, temp_dir: str):
137
- """Test that __init__ raises ValueError for missing versions in JSON."""
138
- missing_versions_path = os.path.join(temp_dir, "missing.json")
139
- with open(missing_versions_path, "w") as f:
140
- json.dump({"defaultVersionId": "default"}, f)
141
-
142
- with pytest.raises(KeyError):
143
- _FilePromptStorage(temp_dir)
144
-
145
- @pytest.mark.asyncio
146
- async def test_exists_returns_true_for_existing_prompt(
147
- self, temp_dir: str, sample_prompt_data: Dict[str, Dict]
148
- ):
149
- """Test that exists returns True for existing prompts."""
150
- self.create_sample_files(temp_dir, sample_prompt_data)
151
- storage = _FilePromptStorage(temp_dir)
152
-
153
- assert storage.exists("prompt1") is True
154
- assert storage.exists("prompt2") is True
155
-
156
- @pytest.mark.asyncio
157
- async def test_exists_returns_false_for_non_existing_prompt(self, temp_dir: str):
158
- """Test that exists returns False for non-existing prompts."""
159
- storage = _FilePromptStorage(temp_dir)
160
-
161
- assert storage.exists("nonexistent") is False
162
-
163
- @pytest.mark.asyncio
164
- async def test_save_creates_new_prompt(self, temp_dir: str):
165
- """Test that save creates a new prompt and returns True."""
166
- storage = _FilePromptStorage(temp_dir)
167
-
168
- prompt = BaseUntypedPrompt(
169
- versions={"v1": "Hello {name}", "v2": "Hi {name}"},
170
- default_version_id="v1",
171
- id="new_prompt",
172
- )
173
-
174
- # Save should work for new prompts now and return True
175
- result = storage.save(prompt)
176
- assert result is True
177
-
178
- # Verify file was created
179
- filepath = os.path.join(temp_dir, "new_prompt.json")
180
- assert os.path.exists(filepath)
181
-
182
- # Verify content
183
- with open(filepath, "r") as f:
184
- data = json.load(f)
185
- assert data["versions"] == {"v1": "Hello {name}", "v2": "Hi {name}"}
186
- assert data["defaultVersionId"] == "v1"
187
- assert "variablesSchema" in data
188
-
189
- @pytest.mark.asyncio
190
- async def test_save_updates_existing_prompt(
191
- self, temp_dir: str, sample_prompt_data: Dict[str, Dict]
192
- ):
193
- """Test that save updates an existing prompt and returns False."""
194
- self.create_sample_files(temp_dir, sample_prompt_data)
195
- storage = _FilePromptStorage(temp_dir)
196
-
197
- # Register the loaded prompts
198
- from pixie.prompts.prompt import BasePrompt
199
-
200
- for p in storage._prompts.values():
201
- BasePrompt.from_untyped(p)
202
-
203
- # Modify the existing prompt
204
- storage._prompts["prompt1"]
205
- updated_versions = {"v1": "Updated {name}", "v3": "New version"}
206
- updated_prompt = BaseUntypedPrompt(
207
- versions=updated_versions, default_version_id="v1", id="prompt1"
208
- )
209
-
210
- result = storage.save(updated_prompt)
211
- assert result is False # Should return False for existing prompt
212
-
213
- # Check in-memory was updated
214
- assert storage._prompts["prompt1"] is updated_prompt
215
- assert storage._prompts["prompt1"].get_versions() == updated_versions
216
-
217
- # Check file was updated
218
- filepath = os.path.join(temp_dir, "prompt1.json")
219
- with open(filepath, "r") as f:
220
- data = json.load(f)
221
- assert data["versions"] == updated_versions
222
- assert data["defaultVersionId"] == "v1"
223
-
224
- @pytest.mark.asyncio
225
- async def test_get_returns_existing_prompt(
226
- self, temp_dir: str, sample_prompt_data: Dict[str, Dict]
227
- ):
228
- """Test that get returns the correct prompt for existing ID."""
229
- self.create_sample_files(temp_dir, sample_prompt_data)
230
- storage = _FilePromptStorage(temp_dir)
231
-
232
- prompt = storage.get("prompt1")
233
- assert isinstance(prompt, BaseUntypedPrompt)
234
- assert prompt.id == "prompt1"
235
- assert prompt.get_versions() == sample_prompt_data["prompt1"]["versions"]
236
- assert (
237
- prompt.get_default_version_id()
238
- == sample_prompt_data["prompt1"]["defaultVersionId"]
239
- )
240
-
241
- @pytest.mark.asyncio
242
- async def test_get_raises_keyerror_for_non_existing_prompt(self, temp_dir: str):
243
- """Test that get raises KeyError for non-existing prompt ID."""
244
- storage = _FilePromptStorage(temp_dir)
245
-
246
- with pytest.raises(KeyError):
247
- storage.get("nonexistent")
248
-
249
- @pytest.mark.asyncio
250
- async def test_save_writes_to_file_before_memory_update(self, temp_dir: str):
251
- """Test that save creates a new prompt successfully."""
252
- storage = _FilePromptStorage(temp_dir)
253
-
254
- prompt = BaseUntypedPrompt(
255
- versions={"default": "Test"}, default_version_id="default", id="test_prompt"
256
- )
257
-
258
- result = storage.save(prompt)
259
- assert result is True
260
-
261
- # Verify it was saved to file
262
- filepath = os.path.join(temp_dir, "test_prompt.json")
263
- assert os.path.exists(filepath)
264
-
265
- @pytest.mark.asyncio
266
- async def test_init_with_default_version_id_none(self, temp_dir: str):
267
- """Test loading a prompt where defaultVersionId is missing (defaults to first version)."""
268
- filepath = os.path.join(temp_dir, "prompt.json")
269
- with open(filepath, "w") as f:
270
- json.dump(
271
- {
272
- "versions": {"v1": "Version 1"},
273
- "defaultVersionId": "v1",
274
- "variablesSchema": {"type": "object", "properties": {}},
275
- },
276
- f,
277
- )
278
-
279
- storage = _FilePromptStorage(temp_dir)
280
- prompt = storage._prompts["prompt"]
281
- assert prompt.get_default_version_id() == "v1" # Defaults to first version
282
-
283
- @pytest.mark.asyncio
284
- async def test_save_validates_schema_compatibility(self, temp_dir: str):
285
- """Test that save validates schema compatibility when updating prompts."""
286
- # Create initial prompt with schema
287
- initial_prompt = BaseUntypedPrompt(
288
- versions={"v1": "Hello"},
289
- default_version_id="v1",
290
- id="schema_test",
291
- variables_schema={
292
- "type": "object",
293
- "properties": {"name": {"type": "string"}},
294
- "required": ["name"],
295
- },
296
- )
297
-
298
- storage = _FilePromptStorage(temp_dir)
299
- storage.save(initial_prompt)
300
-
301
- # Try to update with incompatible schema (removing required field)
302
- updated_prompt = BaseUntypedPrompt(
303
- versions={"v1": "Hello"},
304
- default_version_id="v1",
305
- id="schema_test",
306
- variables_schema={
307
- "type": "object",
308
- "properties": {"age": {"type": "integer"}},
309
- "required": ["age"],
310
- },
311
- )
312
-
313
- # Should raise TypeError due to incompatible schema
314
- with pytest.raises(TypeError):
315
- storage.save(updated_prompt)
316
-
317
- @pytest.mark.asyncio
318
- async def test_save_allows_compatible_schema_extension(self, temp_dir: str):
319
- """Test that save allows extending schema with compatible changes."""
320
- # Create initial prompt with broader schema
321
- initial_prompt = BaseUntypedPrompt(
322
- versions={"v1": "Hello"},
323
- default_version_id="v1",
324
- id="schema_test",
325
- variables_schema={
326
- "type": "object",
327
- "properties": {
328
- "name": {"type": "string"},
329
- "age": {"type": "integer"},
330
- },
331
- },
332
- )
333
-
334
- storage = _FilePromptStorage(temp_dir)
335
- storage.save(initial_prompt)
336
-
337
- # Update with narrower but compatible schema (fewer fields)
338
- # Original schema is a subschema of new schema if new schema is more permissive
339
- updated_prompt = BaseUntypedPrompt(
340
- versions={"v1": "Hello"},
341
- default_version_id="v1",
342
- id="schema_test",
343
- variables_schema={
344
- "type": "object",
345
- "properties": {"name": {"type": "string"}},
346
- },
347
- )
348
-
349
- # Should succeed - removing optional fields makes schema more permissive
350
- result = storage.save(updated_prompt)
351
- assert result is False # Existing prompt
352
-
353
- @pytest.mark.asyncio
354
- async def test_storage_backed_prompt_lazy_loading(self, temp_dir: str):
355
- """Test that StorageBackedPrompt loads from storage on first access."""
356
- from pixie.prompts.storage import (
357
- initialize_prompt_storage,
358
- StorageBackedPrompt,
359
- )
360
-
361
- # Create prompt file directly
362
- import json
363
- import os
364
-
365
- prompt_file = os.path.join(temp_dir, "test_prompt.json")
366
- with open(prompt_file, "w") as f:
367
- json.dump(
368
- {
369
- "versions": {"v1": "Hello {name}"},
370
- "defaultVersionId": "v1",
371
- "variablesSchema": {"type": "object", "properties": {}},
372
- },
373
- f,
374
- )
375
-
376
- # Initialize storage - it will load existing files
377
- initialize_prompt_storage(temp_dir)
378
-
379
- # Create StorageBackedPrompt - should not load yet
380
- backed_prompt = StorageBackedPrompt(id="test_prompt")
381
- assert backed_prompt._prompt is None
382
-
383
- # Access versions - should trigger loading
384
- versions = backed_prompt.get_versions()
385
- assert versions == {"v1": "Hello {name}"}
386
- assert backed_prompt._prompt is not None
387
-
388
- @pytest.mark.asyncio
389
- async def test_storage_backed_prompt_compile(self, temp_dir: str):
390
- """Test that StorageBackedPrompt.compile works correctly."""
391
- from pixie.prompts.storage import (
392
- initialize_prompt_storage,
393
- StorageBackedPrompt,
394
- )
395
- from pixie.prompts.prompt import PromptVariables
396
-
397
- class TestVars(PromptVariables):
398
- name: str
399
-
400
- # Create prompt file directly
401
- import json
402
- import os
403
-
404
- prompt_file = os.path.join(temp_dir, "test_prompt.json")
405
- with open(prompt_file, "w") as f:
406
- json.dump(
407
- {
408
- "versions": {"v1": "Hello {{name}}!"},
409
- "defaultVersionId": "v1",
410
- "variablesSchema": {"type": "object", "properties": {}},
411
- },
412
- f,
413
- )
414
-
415
- # Initialize storage
416
- initialize_prompt_storage(temp_dir)
417
-
418
- # Create StorageBackedPrompt with variable definition
419
- backed_prompt = StorageBackedPrompt(
420
- id="test_prompt", variables_definition=TestVars
421
- )
422
-
423
- # Compile
424
- variables = TestVars(name="World")
425
- result = backed_prompt.compile(variables)
426
- assert result == "Hello World!"
427
-
428
- @pytest.mark.asyncio
429
- async def test_storage_backed_prompt_raises_without_init(self):
430
- """Test that StorageBackedPrompt raises error if storage not initialized."""
431
- from pixie.prompts.storage import StorageBackedPrompt
432
- import pixie.prompts.storage as storage_module
433
-
434
- # Ensure storage is not initialized
435
- storage_module._storage_instance = None
436
-
437
- backed_prompt = StorageBackedPrompt(id="test_prompt")
438
-
439
- with pytest.raises(
440
- RuntimeError, match="Prompt storage has not been initialized"
441
- ):
442
- backed_prompt.get_versions()
443
-
444
- @pytest.mark.asyncio
445
- async def test_create_prompt_helper(self, temp_dir: str):
446
- """Test the create_prompt helper function."""
447
- from pixie.prompts.storage import initialize_prompt_storage
448
- from pixie.prompts.prompt_management import create_prompt
449
-
450
- # Create prompt file directly
451
- import json
452
- import os
453
-
454
- prompt_file = os.path.join(temp_dir, "helper_test.json")
455
- with open(prompt_file, "w") as f:
456
- json.dump(
457
- {
458
- "versions": {"v1": "Test"},
459
- "defaultVersionId": "v1",
460
- "variablesSchema": {"type": "object", "properties": {}},
461
- },
462
- f,
463
- )
464
-
465
- # Initialize storage
466
- initialize_prompt_storage(temp_dir)
467
-
468
- # Create prompt using helper
469
- prompt = create_prompt(id="helper_test")
470
- assert prompt.id == "helper_test"
471
-
472
- versions = prompt.get_versions()
473
- assert versions == {"v1": "Test"}
474
-
475
- @pytest.mark.asyncio
476
- async def test_storage_backed_prompt_schema_compatibility_check_passes(
477
- self, temp_dir: str
478
- ):
479
- """Test that schema compatibility check passes when definition is subschema of storage."""
480
- from pixie.prompts.storage import (
481
- initialize_prompt_storage,
482
- StorageBackedPrompt,
483
- )
484
- from pixie.prompts.prompt import PromptVariables
485
-
486
- class TestVars(PromptVariables):
487
- name: str
488
-
489
- # Create prompt file with empty schema (accepts everything)
490
- import json
491
- import os
492
-
493
- prompt_file = os.path.join(temp_dir, "schema_test.json")
494
- with open(prompt_file, "w") as f:
495
- json.dump(
496
- {
497
- "versions": {"v1": "Hello {name}!"},
498
- "defaultVersionId": "v1",
499
- "variablesSchema": {
500
- "type": "object",
501
- "properties": {},
502
- }, # Empty schema
503
- },
504
- f,
505
- )
506
-
507
- # Initialize storage
508
- initialize_prompt_storage(temp_dir)
509
-
510
- # Create StorageBackedPrompt with restrictive definition
511
- backed_prompt = StorageBackedPrompt(
512
- id="schema_test", variables_definition=TestVars
513
- )
514
-
515
- # Should not raise, since TestVars schema is subschema of empty
516
- versions = backed_prompt.get_versions()
517
- assert versions == {"v1": "Hello {name}!"}
518
-
519
- @pytest.mark.asyncio
520
- async def test_storage_backed_prompt_schema_compatibility_check_fails(
521
- self, temp_dir: str
522
- ):
523
- """Test that schema compatibility check fails when definition is not subschema of storage."""
524
- from pixie.prompts.storage import (
525
- initialize_prompt_storage,
526
- StorageBackedPrompt,
527
- )
528
-
529
- # Create prompt file with restrictive schema (requires name)
530
- import json
531
- import os
532
-
533
- prompt_file = os.path.join(temp_dir, "schema_fail_test.json")
534
- with open(prompt_file, "w") as f:
535
- json.dump(
536
- {
537
- "versions": {"v1": "Hello {name}!"},
538
- "defaultVersionId": "v1",
539
- "variablesSchema": {
540
- "type": "object",
541
- "properties": {"name": {"type": "string"}},
542
- "required": ["name"],
543
- },
544
- },
545
- f,
546
- )
547
-
548
- # Initialize storage
549
- initialize_prompt_storage(temp_dir)
550
-
551
- # Create StorageBackedPrompt with NoneType (empty schema)
552
- backed_prompt = StorageBackedPrompt(
553
- id="schema_fail_test", variables_definition=NoneType
554
- )
555
-
556
- # Should raise TypeError because empty schema is not subschema of required schema
557
- with pytest.raises(
558
- TypeError,
559
- match="The provided variables_definition is not compatible with the prompt's variables schema",
560
- ):
561
- backed_prompt.get_versions()
562
-
563
- @pytest.mark.asyncio
564
- async def test_storage_backed_prompt_actualize(self, temp_dir: str):
565
- """Test that StorageBackedPrompt.actualize() loads the prompt and returns self."""
566
- from pixie.prompts.storage import (
567
- initialize_prompt_storage,
568
- StorageBackedPrompt,
569
- )
570
-
571
- # Create prompt file directly
572
- import json
573
- import os
574
-
575
- prompt_file = os.path.join(temp_dir, "actualize_test.json")
576
- with open(prompt_file, "w") as f:
577
- json.dump(
578
- {
579
- "versions": {"v1": "Hello {name}"},
580
- "defaultVersionId": "v1",
581
- "variablesSchema": {"type": "object", "properties": {}},
582
- },
583
- f,
584
- )
585
-
586
- # Initialize storage
587
- initialize_prompt_storage(temp_dir)
588
-
589
- # Create StorageBackedPrompt - should not load yet
590
- backed_prompt = StorageBackedPrompt(id="actualize_test")
591
- assert backed_prompt._prompt is None
592
-
593
- # Call actualize - should load and return self
594
- result = backed_prompt.actualize()
595
- assert result is backed_prompt
596
- assert backed_prompt._prompt is not None
597
-
598
- # Verify it works
599
- versions = backed_prompt.get_versions()
600
- assert versions == {"v1": "Hello {name}"}
601
-
602
- @pytest.mark.asyncio
603
- async def test_list_prompts_empty(self):
604
- """Test that list_prompts returns empty list initially."""
605
- from pixie.prompts.prompt_management import list_prompts
606
- import pixie.prompts.prompt_management as pm_module
607
-
608
- # Clear the registry
609
- pm_module._registry.clear()
610
-
611
- prompts = list_prompts()
612
- assert prompts == []
613
-
614
- @pytest.mark.asyncio
615
- async def test_get_prompt_nonexistent(self):
616
- """Test that get_prompt returns None for non-existent prompt."""
617
- from pixie.prompts.prompt_management import get_prompt
618
- import pixie.prompts.prompt_management as pm_module
619
-
620
- # Clear the registry
621
- pm_module._registry.clear()
622
-
623
- prompt = get_prompt("nonexistent")
624
- assert prompt is None
625
-
626
- @pytest.mark.asyncio
627
- async def test_create_prompt_new(self, temp_dir: str):
628
- """Test creating a new prompt with create_prompt."""
629
- from pixie.prompts.storage import initialize_prompt_storage
630
- from pixie.prompts.prompt_management import (
631
- create_prompt,
632
- get_prompt,
633
- list_prompts,
634
- )
635
- import pixie.prompts.prompt_management as pm_module
636
-
637
- # Clear the registry and initialize storage
638
- pm_module._registry.clear()
639
- initialize_prompt_storage(temp_dir)
640
-
641
- # Create prompt file
642
- import json
643
- import os
644
-
645
- prompt_file = os.path.join(temp_dir, "create_test.json")
646
- with open(prompt_file, "w") as f:
647
- json.dump(
648
- {
649
- "versions": {"v1": "Hello {name}"},
650
- "defaultVersionId": "v1",
651
- "variablesSchema": {"type": "object", "properties": {}},
652
- },
653
- f,
654
- )
655
-
656
- # Create new prompt
657
- prompt = create_prompt(id="create_test")
658
- assert prompt.id == "create_test"
659
- assert prompt.variables_definition == NoneType
660
-
661
- # Should be in registry
662
- prompt_with_registration = get_prompt("create_test")
663
- assert prompt_with_registration is not None
664
- retrieved = prompt_with_registration.prompt
665
- assert retrieved is prompt
666
-
667
- # Should be in list
668
- prompts = list_prompts()
669
- assert len(prompts) == 1
670
- assert prompts[0].prompt is prompt
671
-
672
- @pytest.mark.asyncio
673
- async def test_create_prompt_existing_same_definition(self, temp_dir: str):
674
- """Test getting existing prompt with same variables_definition."""
675
- from pixie.prompts.storage import initialize_prompt_storage
676
- from pixie.prompts.prompt_management import create_prompt
677
- import pixie.prompts.prompt_management as pm_module
678
- from pixie.prompts.prompt import PromptVariables
679
-
680
- class TestVars(PromptVariables):
681
- name: str
682
-
683
- # Clear the registry and initialize storage
684
- pm_module._registry.clear()
685
- initialize_prompt_storage(temp_dir)
686
-
687
- # Create prompt file
688
- import json
689
- import os
690
-
691
- prompt_file = os.path.join(temp_dir, "existing_test.json")
692
- with open(prompt_file, "w") as f:
693
- json.dump(
694
- {
695
- "versions": {"v1": "Hello {name}"},
696
- "defaultVersionId": "v1",
697
- "variablesSchema": {"type": "object", "properties": {}},
698
- },
699
- f,
700
- )
701
-
702
- # Create prompt first time
703
- prompt1 = create_prompt(id="existing_test", variables_definition=TestVars)
704
- assert prompt1.variables_definition == TestVars
705
-
706
- # Create same prompt second time - should return same instance
707
- prompt2 = create_prompt(id="existing_test", variables_definition=TestVars)
708
- assert prompt2 is prompt1
709
-
710
- @pytest.mark.asyncio
711
- async def test_create_prompt_existing_different_definition_raises(
712
- self, temp_dir: str
713
- ):
714
- """Test that creating prompt with different variables_definition raises error."""
715
- from pixie.prompts.storage import initialize_prompt_storage
716
- from pixie.prompts.prompt_management import create_prompt
717
- import pixie.prompts.prompt_management as pm_module
718
- from pixie.prompts.prompt import PromptVariables
719
-
720
- class TestVars1(PromptVariables):
721
- name: str
722
-
723
- class TestVars2(PromptVariables):
724
- age: int
725
-
726
- # Clear the registry and initialize storage
727
- pm_module._registry.clear()
728
- initialize_prompt_storage(temp_dir)
729
-
730
- # Create prompt file
731
- import json
732
- import os
733
-
734
- prompt_file = os.path.join(temp_dir, "conflict_test.json")
735
- with open(prompt_file, "w") as f:
736
- json.dump(
737
- {
738
- "versions": {"v1": "Hello {name}"},
739
- "defaultVersionId": "v1",
740
- "variablesSchema": {"type": "object", "properties": {}},
741
- },
742
- f,
743
- )
744
-
745
- # Create prompt first time
746
- create_prompt(id="conflict_test", variables_definition=TestVars1)
747
-
748
- # Try to create with different definition - should raise
749
- with pytest.raises(
750
- ValueError,
751
- match="Prompt with id 'conflict_test' already exists with a different variables definition",
752
- ):
753
- create_prompt(id="conflict_test", variables_definition=TestVars2)
754
-
755
- @pytest.mark.asyncio
756
- async def test_storage_backed_prompt_properties(self, temp_dir: str):
757
- """Test StorageBackedPrompt id and variables_definition properties."""
758
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
759
- from pixie.prompts.prompt import PromptVariables
760
-
761
- class TestVars(PromptVariables):
762
- name: str
763
-
764
- initialize_prompt_storage(temp_dir)
765
-
766
- prompt = StorageBackedPrompt(id="test_id", variables_definition=TestVars)
767
- assert prompt.id == "test_id"
768
- assert prompt.variables_definition == TestVars
769
-
770
- @pytest.mark.asyncio
771
- async def test_storage_backed_prompt_get_variables_schema(self, temp_dir: str):
772
- """Test StorageBackedPrompt.get_variables_schema."""
773
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
774
- from pixie.prompts.prompt import PromptVariables
775
-
776
- class TestVars(PromptVariables):
777
- name: str
778
- age: int
779
-
780
- initialize_prompt_storage(temp_dir)
781
-
782
- prompt = StorageBackedPrompt(id="test_id", variables_definition=TestVars)
783
- schema = prompt.get_variables_schema()
784
- assert schema == {
785
- "type": "object",
786
- "title": "TestVars",
787
- "properties": {
788
- "name": {"title": "Name", "type": "string"},
789
- "age": {"title": "Age", "type": "integer"},
790
- },
791
- "required": ["name", "age"],
792
- }
793
-
794
- @pytest.mark.asyncio
795
- async def test_storage_backed_prompt_exists_in_storage_true(self, temp_dir: str):
796
- """Test exists_in_storage returns True when prompt exists."""
797
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
798
-
799
- # Create prompt file
800
- import json
801
- import os
802
-
803
- prompt_file = os.path.join(temp_dir, "exists_test.json")
804
- with open(prompt_file, "w") as f:
805
- json.dump(
806
- {
807
- "versions": {"v1": "Hello"},
808
- "defaultVersionId": "v1",
809
- "variablesSchema": {"type": "object", "properties": {}},
810
- },
811
- f,
812
- )
813
-
814
- initialize_prompt_storage(temp_dir)
815
-
816
- prompt = StorageBackedPrompt(id="exists_test")
817
- assert prompt.exists_in_storage() is True
818
-
819
- @pytest.mark.asyncio
820
- async def test_storage_backed_prompt_exists_in_storage_false(self, temp_dir: str):
821
- """Test exists_in_storage returns False when prompt does not exist."""
822
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
823
-
824
- initialize_prompt_storage(temp_dir)
825
-
826
- prompt = StorageBackedPrompt(id="nonexistent")
827
- assert prompt.exists_in_storage() is False
828
-
829
- @pytest.mark.asyncio
830
- async def test_storage_backed_prompt_get_default_version_id(self, temp_dir: str):
831
- """Test StorageBackedPrompt.get_default_version_id."""
832
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
833
-
834
- # Create prompt file
835
- import json
836
- import os
837
-
838
- prompt_file = os.path.join(temp_dir, "default_test.json")
839
- with open(prompt_file, "w") as f:
840
- json.dump(
841
- {
842
- "versions": {"v1": "Version 1", "v2": "Version 2"},
843
- "defaultVersionId": "v2",
844
- "variablesSchema": {"type": "object", "properties": {}},
845
- },
846
- f,
847
- )
848
-
849
- initialize_prompt_storage(temp_dir)
850
-
851
- prompt = StorageBackedPrompt(id="default_test")
852
- default_id = prompt.get_default_version_id()
853
- assert default_id == "v2"
854
-
855
- @pytest.mark.asyncio
856
- async def test_storage_backed_prompt_append_version(self, temp_dir: str):
857
- """Test that StorageBackedPrompt.append_version works correctly."""
858
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
859
-
860
- # Create prompt file
861
- import json
862
- import os
863
-
864
- prompt_file = os.path.join(temp_dir, "append_test.json")
865
- with open(prompt_file, "w") as f:
866
- json.dump(
867
- {
868
- "versions": {"v1": "Hello {name}"},
869
- "defaultVersionId": "v1",
870
- "variablesSchema": {"type": "object", "properties": {}},
871
- },
872
- f,
873
- )
874
-
875
- initialize_prompt_storage(temp_dir)
876
-
877
- prompt = StorageBackedPrompt(id="append_test")
878
-
879
- # Append new version
880
- result_prompt = prompt.append_version(
881
- version_id="v2", content="Hi {name}", set_as_default=True
882
- )
883
-
884
- # Check that it returns the underlying BasePrompt
885
- assert isinstance(result_prompt, BasePrompt)
886
- assert result_prompt.id == "append_test"
887
-
888
- # Check versions were updated
889
- versions = result_prompt.get_versions()
890
- assert "v2" in versions
891
- assert versions["v2"] == "Hi {name}"
892
- assert result_prompt.get_default_version_id() == "v2"
893
-
894
- # Check that storage was updated
895
- storage = _FilePromptStorage(temp_dir)
896
- stored_prompt = storage.get("append_test")
897
- stored_versions = stored_prompt.get_versions()
898
- assert "v2" in stored_versions
899
- assert stored_versions["v2"] == "Hi {name}"
900
- assert stored_prompt.get_default_version_id() == "v2"
901
-
902
- @pytest.mark.asyncio
903
- async def test_storage_backed_prompt_append_version_creates_new_prompt(
904
- self, temp_dir: str
905
- ):
906
- """Test that StorageBackedPrompt.append_version creates a new prompt if it doesn't exist."""
907
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
908
-
909
- initialize_prompt_storage(temp_dir)
910
-
911
- prompt = StorageBackedPrompt(id="new_append_test")
912
-
913
- # Append version to non-existing prompt (should create new)
914
- result_prompt = prompt.append_version(
915
- version_id="v1", content="Hello {name}", set_as_default=True
916
- )
917
-
918
- # Check that it returns the underlying BasePrompt
919
- assert isinstance(result_prompt, BasePrompt)
920
- assert result_prompt.id == "new_append_test"
921
-
922
- # Check versions
923
- versions = result_prompt.get_versions()
924
- assert "v1" in versions
925
- assert versions["v1"] == "Hello {name}"
926
- assert result_prompt.get_default_version_id() == "v1"
927
-
928
- # Check that storage was created
929
- storage = _FilePromptStorage(temp_dir)
930
- stored_prompt = storage.get("new_append_test")
931
- stored_versions = stored_prompt.get_versions()
932
- assert "v1" in stored_versions
933
- assert stored_versions["v1"] == "Hello {name}"
934
- assert stored_prompt.get_default_version_id() == "v1"
935
-
936
- @pytest.mark.asyncio
937
- async def test_storage_backed_prompt_update_default_version_id(self, temp_dir: str):
938
- """Test that StorageBackedPrompt.update_default_version_id works correctly."""
939
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
940
-
941
- # Create prompt file with multiple versions
942
- import json
943
- import os
944
-
945
- prompt_file = os.path.join(temp_dir, "update_default_test.json")
946
- with open(prompt_file, "w") as f:
947
- json.dump(
948
- {
949
- "versions": {
950
- "v1": "Version 1",
951
- "v2": "Version 2",
952
- "v3": "Version 3",
953
- },
954
- "defaultVersionId": "v1",
955
- "variablesSchema": {"type": "object", "properties": {}},
956
- },
957
- f,
958
- )
959
-
960
- initialize_prompt_storage(temp_dir)
961
-
962
- prompt = StorageBackedPrompt(id="update_default_test")
963
-
964
- # Update default version
965
- result_prompt = prompt.update_default_version_id("v3")
966
-
967
- # Check that it returns the underlying BasePrompt
968
- assert isinstance(result_prompt, BasePrompt)
969
- assert result_prompt.id == "update_default_test"
970
- assert result_prompt.get_default_version_id() == "v3"
971
-
972
- # Check that storage was updated
973
- storage = _FilePromptStorage(temp_dir)
974
- stored_prompt = storage.get("update_default_test")
975
- assert stored_prompt.get_default_version_id() == "v3"
976
-
977
- @pytest.mark.asyncio
978
- async def test_storage_backed_prompt_exists_in_storage_without_init_raises_error(
979
- self,
980
- ):
981
- """Test exists_in_storage raises error when storage not initialized."""
982
- from pixie.prompts.storage import StorageBackedPrompt
983
- import pixie.prompts.storage as storage_module
984
-
985
- # Ensure storage is not initialized
986
- storage_module._storage_instance = None
987
-
988
- prompt = StorageBackedPrompt(id="test")
989
-
990
- with pytest.raises(
991
- RuntimeError, match="Prompt storage has not been initialized"
992
- ):
993
- prompt.exists_in_storage()
994
-
995
- @pytest.mark.asyncio
996
- async def test_storage_backed_prompt_actualize_loads_prompt(self, temp_dir: str):
997
- """Test that actualize loads the prompt and returns self."""
998
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
999
-
1000
- # Create prompt file directly
1001
- import json
1002
- import os
1003
-
1004
- prompt_file = os.path.join(temp_dir, "actualize_test.json")
1005
- with open(prompt_file, "w") as f:
1006
- json.dump(
1007
- {
1008
- "versions": {"v1": "Hello {name}"},
1009
- "defaultVersionId": "v1",
1010
- "variablesSchema": {"type": "object", "properties": {}},
1011
- },
1012
- f,
1013
- )
1014
-
1015
- initialize_prompt_storage(temp_dir)
1016
-
1017
- prompt = StorageBackedPrompt(id="actualize_test")
1018
- assert prompt._prompt is None
1019
-
1020
- # Call actualize
1021
- result = prompt.actualize()
1022
- assert result is prompt
1023
- assert prompt._prompt is not None
1024
-
1025
- # Verify it works
1026
- versions = prompt.get_versions()
1027
- assert versions == {"v1": "Hello {name}"}
1028
-
1029
- @pytest.mark.asyncio
1030
- async def test_storage_backed_prompt_actualize_with_variables_definition(
1031
- self, temp_dir: str
1032
- ):
1033
- """Test actualize with variables_definition performs schema compatibility check."""
1034
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1035
- from pixie.prompts.prompt import PromptVariables
1036
-
1037
- class TestVars(PromptVariables):
1038
- name: str
1039
-
1040
- # Create prompt file with compatible schema
1041
- import json
1042
- import os
1043
-
1044
- prompt_file = os.path.join(temp_dir, "actualize_vars_test.json")
1045
- with open(prompt_file, "w") as f:
1046
- json.dump(
1047
- {
1048
- "versions": {"v1": "Hello {name}"},
1049
- "defaultVersionId": "v1",
1050
- "variablesSchema": {
1051
- "type": "object",
1052
- "properties": {"name": {"type": "string"}},
1053
- "required": ["name"],
1054
- },
1055
- },
1056
- f,
1057
- )
1058
-
1059
- initialize_prompt_storage(temp_dir)
1060
-
1061
- prompt = StorageBackedPrompt(
1062
- id="actualize_vars_test", variables_definition=TestVars
1063
- )
1064
-
1065
- # Should succeed - schemas are compatible
1066
- result = prompt.actualize()
1067
- assert result is prompt
1068
- assert prompt._prompt is not None
1069
-
1070
- @pytest.mark.asyncio
1071
- async def test_storage_backed_prompt_actualize_incompatible_schema_raises_error(
1072
- self, temp_dir: str
1073
- ):
1074
- """Test actualize raises error when schema is incompatible."""
1075
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1076
- from pixie.prompts.prompt import PromptVariables
1077
-
1078
- class TestVars(PromptVariables):
1079
- age: int # Different from what's in storage
1080
-
1081
- # Create prompt file with incompatible schema
1082
- import json
1083
- import os
1084
-
1085
- prompt_file = os.path.join(temp_dir, "incompatible_test.json")
1086
- with open(prompt_file, "w") as f:
1087
- json.dump(
1088
- {
1089
- "versions": {"v1": "Hello {name}"},
1090
- "defaultVersionId": "v1",
1091
- "variablesSchema": {
1092
- "type": "object",
1093
- "properties": {"name": {"type": "string"}},
1094
- "required": ["name"],
1095
- },
1096
- },
1097
- f,
1098
- )
1099
-
1100
- initialize_prompt_storage(temp_dir)
1101
-
1102
- prompt = StorageBackedPrompt(
1103
- id="incompatible_test", variables_definition=TestVars
1104
- )
1105
-
1106
- # Should raise TypeError due to incompatible schema
1107
- with pytest.raises(
1108
- TypeError, match="The provided variables_definition is not compatible"
1109
- ):
1110
- prompt.actualize()
1111
-
1112
- @pytest.mark.asyncio
1113
- async def test_storage_backed_prompt_append_version_updates_storage(
1114
- self, temp_dir: str
1115
- ):
1116
- """Test that append_version updates the storage file."""
1117
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1118
-
1119
- # Create initial prompt file
1120
- import json
1121
- import os
1122
-
1123
- prompt_file = os.path.join(temp_dir, "storage_update_test.json")
1124
- with open(prompt_file, "w") as f:
1125
- json.dump(
1126
- {
1127
- "versions": {"v1": "Initial"},
1128
- "defaultVersionId": "v1",
1129
- "variablesSchema": {"type": "object", "properties": {}},
1130
- },
1131
- f,
1132
- )
1133
-
1134
- initialize_prompt_storage(temp_dir)
1135
-
1136
- prompt = StorageBackedPrompt(id="storage_update_test")
1137
-
1138
- # Append version
1139
- prompt.append_version(version_id="v2", content="Added version")
1140
-
1141
- # Check file was updated
1142
- with open(prompt_file, "r") as f:
1143
- data = json.load(f)
1144
-
1145
- assert "v2" in data["versions"]
1146
- assert data["versions"]["v2"] == "Added version"
1147
-
1148
- @pytest.mark.asyncio
1149
- async def test_storage_backed_prompt_update_default_updates_storage(
1150
- self, temp_dir: str
1151
- ):
1152
- """Test that update_default_version_id updates the storage file."""
1153
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1154
-
1155
- # Create initial prompt file
1156
- import json
1157
- import os
1158
-
1159
- prompt_file = os.path.join(temp_dir, "default_update_test.json")
1160
- with open(prompt_file, "w") as f:
1161
- json.dump(
1162
- {
1163
- "versions": {"v1": "Version 1", "v2": "Version 2"},
1164
- "defaultVersionId": "v1",
1165
- "variablesSchema": {"type": "object", "properties": {}},
1166
- },
1167
- f,
1168
- )
1169
-
1170
- initialize_prompt_storage(temp_dir)
1171
-
1172
- prompt = StorageBackedPrompt(id="default_update_test")
1173
-
1174
- # Update default
1175
- prompt.update_default_version_id("v2")
1176
-
1177
- # Check file was updated
1178
- with open(prompt_file, "r") as f:
1179
- data = json.load(f)
1180
-
1181
- assert data["defaultVersionId"] == "v2"
1182
-
1183
- @pytest.mark.asyncio
1184
- async def test_storage_backed_prompt_append_version_raises_for_existing_id(
1185
- self, temp_dir: str
1186
- ):
1187
- """Test that append_version raises error for existing version ID."""
1188
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1189
-
1190
- # Create prompt file
1191
- import json
1192
- import os
1193
-
1194
- prompt_file = os.path.join(temp_dir, "duplicate_version_test.json")
1195
- with open(prompt_file, "w") as f:
1196
- json.dump(
1197
- {
1198
- "versions": {"v1": "Version 1"},
1199
- "defaultVersionId": "v1",
1200
- "variablesSchema": {"type": "object", "properties": {}},
1201
- },
1202
- f,
1203
- )
1204
-
1205
- initialize_prompt_storage(temp_dir)
1206
-
1207
- prompt = StorageBackedPrompt(id="duplicate_version_test")
1208
-
1209
- # Try to append existing version
1210
- with pytest.raises(ValueError, match="Version ID 'v1' already exists"):
1211
- prompt.append_version(version_id="v1", content="Duplicate")
1212
-
1213
- @pytest.mark.asyncio
1214
- async def test_storage_backed_prompt_update_default_raises_for_nonexistent_id(
1215
- self, temp_dir: str
1216
- ):
1217
- """Test that update_default_version_id raises error for nonexistent version ID."""
1218
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1219
-
1220
- # Create prompt file
1221
- import json
1222
- import os
1223
-
1224
- prompt_file = os.path.join(temp_dir, "nonexistent_default_test.json")
1225
- with open(prompt_file, "w") as f:
1226
- json.dump(
1227
- {
1228
- "versions": {"v1": "Version 1"},
1229
- "defaultVersionId": "v1",
1230
- "variablesSchema": {"type": "object", "properties": {}},
1231
- },
1232
- f,
1233
- )
1234
-
1235
- initialize_prompt_storage(temp_dir)
1236
-
1237
- prompt = StorageBackedPrompt(id="nonexistent_default_test")
1238
-
1239
- # Try to update to nonexistent version
1240
- with pytest.raises(ValueError, match="Version ID 'nonexistent' does not exist"):
1241
- prompt.update_default_version_id("nonexistent")
1242
-
1243
- @pytest.mark.asyncio
1244
- async def test_storage_backed_prompt_append_version_without_init_raises_error(self):
1245
- """Test that append_version raises error when storage not initialized."""
1246
- from pixie.prompts.storage import StorageBackedPrompt
1247
- import pixie.prompts.storage as storage_module
1248
-
1249
- # Ensure storage is not initialized
1250
- storage_module._storage_instance = None
1251
-
1252
- prompt = StorageBackedPrompt(id="test")
1253
-
1254
- with pytest.raises(
1255
- RuntimeError, match="Prompt storage has not been initialized"
1256
- ):
1257
- prompt.append_version(version_id="v2", content="New version")
1258
-
1259
- @pytest.mark.asyncio
1260
- async def test_storage_backed_prompt_update_default_without_init_raises_error(self):
1261
- """Test that update_default_version_id raises error when storage not initialized."""
1262
- from pixie.prompts.storage import StorageBackedPrompt
1263
- import pixie.prompts.storage as storage_module
1264
-
1265
- # Ensure storage is not initialized
1266
- storage_module._storage_instance = None
1267
-
1268
- prompt = StorageBackedPrompt(id="test")
1269
-
1270
- with pytest.raises(
1271
- RuntimeError, match="Prompt storage has not been initialized"
1272
- ):
1273
- prompt.update_default_version_id("v2")
1274
-
1275
- @pytest.mark.asyncio
1276
- async def test_storage_backed_prompt_deletion_during_runtime(self, temp_dir: str):
1277
- """Test behavior when a prompt is deleted from storage during runtime."""
1278
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1279
- import os
1280
-
1281
- # Create prompt file
1282
- prompt_file = os.path.join(temp_dir, "deletion_test.json")
1283
- with open(prompt_file, "w") as f:
1284
- json.dump(
1285
- {
1286
- "versions": {"v1": "Hello {name}"},
1287
- "defaultVersionId": "v1",
1288
- "variablesSchema": {
1289
- "type": "object",
1290
- "properties": {"name": {"type": "string"}},
1291
- },
1292
- },
1293
- f,
1294
- )
1295
-
1296
- # Initialize storage
1297
- initialize_prompt_storage(temp_dir)
1298
-
1299
- prompt = StorageBackedPrompt(id="deletion_test")
1300
-
1301
- # Delete the prompt file
1302
- os.remove(prompt_file)
1303
-
1304
- # Attempt to access the deleted prompt
1305
- # The prompt is still in storage's in-memory cache, so it should work
1306
- # but raises TypeError due to schema incompatibility with NoneType default
1307
- with pytest.raises(TypeError, match="not compatible"):
1308
- prompt.get_versions()
1309
-
1310
-
1311
- class TestInitializePromptStorage:
1312
- """Tests for initialize_prompt_storage function."""
1313
-
1314
- @pytest.fixture
1315
- def temp_dir(self):
1316
- """Create a temporary directory for testing."""
1317
- with tempfile.TemporaryDirectory() as tmpdir:
1318
- yield tmpdir
1319
-
1320
- @pytest.fixture(autouse=True)
1321
- def reset_storage_instance(self):
1322
- """Reset the global storage instance before each test."""
1323
- import pixie.prompts.storage as storage_module
1324
-
1325
- storage_module._storage_instance = None
1326
- yield
1327
- storage_module._storage_instance = None
1328
-
1329
- def test_initialize_prompt_storage_once(self, temp_dir: str):
1330
- """Test that initialize_prompt_storage can only be called once."""
1331
- from pixie.prompts.storage import initialize_prompt_storage
1332
-
1333
- initialize_prompt_storage(temp_dir)
1334
-
1335
- # Should raise error on second call
1336
- with pytest.raises(
1337
- RuntimeError, match="Prompt storage has already been initialized"
1338
- ):
1339
- initialize_prompt_storage(temp_dir)
1340
-
1341
- def test_initialize_creates_storage(self, temp_dir: str):
1342
- """Test that initialize_prompt_storage creates a FilePromptStorage instance."""
1343
- from pixie.prompts.storage import initialize_prompt_storage
1344
- import pixie.prompts.storage as storage_module
1345
-
1346
- initialize_prompt_storage(temp_dir)
1347
-
1348
- assert storage_module._storage_instance is not None
1349
- assert isinstance(storage_module._storage_instance, _FilePromptStorage)
1350
-
1351
- @pytest.mark.asyncio
1352
- async def test_storage_backed_prompt_append_version_schema_incompatibility(
1353
- self, temp_dir: str
1354
- ):
1355
- """Test that appending a version with incompatible schema raises an error."""
1356
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1357
- from pixie.prompts.prompt import PromptVariables
1358
-
1359
- class OriginalVars(PromptVariables):
1360
- name: str
1361
-
1362
- class IncompatibleVars(PromptVariables):
1363
- age: int
1364
-
1365
- # Create prompt file directly
1366
- import json
1367
- import os
1368
-
1369
- prompt_file = os.path.join(temp_dir, "schema_test.json")
1370
- with open(prompt_file, "w") as f:
1371
- json.dump(
1372
- {
1373
- "versions": {"v1": "Hello {name}"},
1374
- "defaultVersionId": "v1",
1375
- "variablesSchema": {
1376
- "type": "object",
1377
- "properties": {"name": {"type": "string"}},
1378
- },
1379
- },
1380
- f,
1381
- )
1382
-
1383
- # Initialize storage
1384
- initialize_prompt_storage(temp_dir)
1385
-
1386
- # Create StorageBackedPrompt with original schema
1387
- prompt = StorageBackedPrompt(
1388
- id="schema_test", variables_definition=OriginalVars
1389
- )
1390
-
1391
- # Attempt to append a version with incompatible schema
1392
- with pytest.raises(TypeError, match="Original schema must be a subschema"):
1393
- prompt.append_version(version_id="v2", content="Hi {age}")
1394
-
1395
- @pytest.mark.asyncio
1396
- async def test_storage_backed_prompt_concurrent_append_version(self, temp_dir: str):
1397
- """Test concurrent calls to append_version to ensure thread safety."""
1398
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1399
- import asyncio
1400
-
1401
- # Initialize storage
1402
- initialize_prompt_storage(temp_dir)
1403
-
1404
- prompt = StorageBackedPrompt(id="concurrent_test")
1405
-
1406
- async def append_version(version_id, content):
1407
- prompt.append_version(version_id=version_id, content=content)
1408
-
1409
- # Run concurrent appends
1410
- await asyncio.gather(
1411
- append_version("v1", "Hello {name}"),
1412
- append_version("v2", "Hi {name}"),
1413
- )
1414
-
1415
- # Check that both versions exist
1416
- versions = prompt.get_versions()
1417
- assert "v1" in versions
1418
- assert "v2" in versions
1419
- assert versions["v1"] == "Hello {name}"
1420
- assert versions["v2"] == "Hi {name}"
1421
-
1422
- @pytest.mark.asyncio
1423
- async def test_storage_backed_prompt_append_version_invalid_version_id(
1424
- self, temp_dir: str
1425
- ):
1426
- """Test that appending a version with an empty version ID works (no validation)."""
1427
- from pixie.prompts.storage import initialize_prompt_storage, StorageBackedPrompt
1428
-
1429
- # Initialize storage
1430
- initialize_prompt_storage(temp_dir)
1431
-
1432
- prompt = StorageBackedPrompt(id="invalid_version_test")
1433
-
1434
- # Empty version ID is actually allowed - no validation in place
1435
- result = prompt.append_version(version_id="", content="Hello {name}")
1436
- assert result is not None
1437
- versions = result.get_versions()
1438
- assert "" in versions
1439
-
1440
- @pytest.mark.asyncio
1441
- async def test_storage_backed_prompt_corrupted_storage(self, temp_dir: str):
1442
- """Test behavior when storage files are corrupted."""
1443
- from pixie.prompts.storage import initialize_prompt_storage
1444
- import os
1445
-
1446
- # Create corrupted prompt file
1447
- corrupted_file = os.path.join(temp_dir, "corrupted_test.json")
1448
- with open(corrupted_file, "w") as f:
1449
- f.write("{invalid_json}")
1450
-
1451
- # Initialize storage - should raise JSONDecodeError when loading corrupted file
1452
- with pytest.raises(json.JSONDecodeError):
1453
- initialize_prompt_storage(temp_dir)