11"""Tests for tokenize helpers used by cache_key()."""
22
3+ import pytest
4+
35from ccflow .callable import CallableModel , ContextBase , EvaluatorBase , ModelEvaluationContext
46from ccflow .context import NullContext
57from ccflow .evaluators .common import cache_key
68from ccflow .result import GenericResult
7- from ccflow .utils .tokenize import compute_behavior_token , compute_data_token
9+ from ccflow .utils .tokenize import compute_behavior_token , compute_cache_token , compute_data_token
810
911# ---------------------------------------------------------------------------
1012# Data token
@@ -21,6 +23,39 @@ def test_different_values_different_tokens(self):
2123 assert compute_data_token ({"x" : 1 }) != compute_data_token ({"x" : 2 })
2224
2325
26+ class TestComputeCacheToken :
27+ def test_deterministic (self ):
28+ class Helper :
29+ def f (self ):
30+ return 1
31+
32+ token1 = compute_cache_token (data_values = [{"x" : 1 }], behavior_classes = [Helper ])
33+ token2 = compute_cache_token (data_values = [{"x" : 1 }], behavior_classes = [Helper ])
34+ assert token1 == token2
35+
36+ def test_data_changes_token (self ):
37+ class Helper :
38+ def f (self ):
39+ return 1
40+
41+ token1 = compute_cache_token (data_values = [{"x" : 1 }], behavior_classes = [Helper ])
42+ token2 = compute_cache_token (data_values = [{"x" : 2 }], behavior_classes = [Helper ])
43+ assert token1 != token2
44+
45+ def test_behavior_changes_token (self ):
46+ class HelperA :
47+ def f (self ):
48+ return 1
49+
50+ class HelperB :
51+ def f (self ):
52+ return 2
53+
54+ token1 = compute_cache_token (data_values = [{"x" : 1 }], behavior_classes = [HelperA ])
55+ token2 = compute_cache_token (data_values = [{"x" : 1 }], behavior_classes = [HelperB ])
56+ assert token1 != token2
57+
58+
2459# ---------------------------------------------------------------------------
2560# Basic behavior
2661# ---------------------------------------------------------------------------
@@ -77,7 +112,7 @@ def f(self):
77112 return 1
78113
79114 token = compute_behavior_token (M )
80- assert M .__behavior_token_cache__ == token
115+ assert M .__ccflow_tokenizer_cache__ == token
81116 # Second call returns cached value
82117 assert compute_behavior_token (M ) is token
83118
@@ -294,6 +329,29 @@ def f(self):
294329
295330 assert compute_behavior_token (A ) != compute_behavior_token (B )
296331
332+ def test_class_dep_included (self ):
333+ class HelperA :
334+ def f (self ):
335+ return 1
336+
337+ class HelperB :
338+ def f (self ):
339+ return 2
340+
341+ class A :
342+ __ccflow_tokenizer_deps__ = [HelperA ]
343+
344+ def f (self ):
345+ return 1
346+
347+ class B :
348+ __ccflow_tokenizer_deps__ = [HelperB ]
349+
350+ def f (self ):
351+ return 1
352+
353+ assert compute_behavior_token (A ) != compute_behavior_token (B )
354+
297355 def test_subclass_deps_extend_inherited_deps (self ):
298356 def base_a ():
299357 return 1
@@ -324,6 +382,21 @@ class SubB(BaseB):
324382
325383 assert compute_behavior_token (SubA ) != compute_behavior_token (SubB )
326384
385+ def test_recursive_class_deps_raise (self ):
386+ class A :
387+ def f (self ):
388+ return 1
389+
390+ class B :
391+ def g (self ):
392+ return 2
393+
394+ A .__ccflow_tokenizer_deps__ = [B ]
395+ B .__ccflow_tokenizer_deps__ = [A ]
396+
397+ with pytest .raises (TypeError , match = "Recursive __ccflow_tokenizer_deps__ class dependency" ):
398+ compute_behavior_token (A )
399+
327400
328401# ---------------------------------------------------------------------------
329402# Integration with cache_key()
@@ -412,6 +485,33 @@ def helper(self, x=2):
412485
413486 assert cache_key (A ()) != cache_key (B ())
414487
488+ def test_class_dep_changes_key (self ):
489+ from ccflow import Flow
490+
491+ class HelperA :
492+ def f (self ):
493+ return 1
494+
495+ class HelperB :
496+ def f (self ):
497+ return 2
498+
499+ class A (CallableModel ):
500+ __ccflow_tokenizer_deps__ = [HelperA ]
501+
502+ @Flow .call
503+ def __call__ (self , context : NullContext ) -> GenericResult :
504+ return GenericResult (value = 1 )
505+
506+ class B (CallableModel ):
507+ __ccflow_tokenizer_deps__ = [HelperB ]
508+
509+ @Flow .call
510+ def __call__ (self , context : NullContext ) -> GenericResult :
511+ return GenericResult (value = 1 )
512+
513+ assert cache_key (A ()) != cache_key (B ())
514+
415515 def test_opaque_evaluator_behavior_changes_key (self ):
416516 from ccflow import Flow
417517
@@ -512,7 +612,7 @@ def __call__(self):
512612 assert compute_behavior_token (Sub ) != compute_behavior_token (Base )
513613
514614 def test_subclass_cache_independent (self ):
515- """Parent and subclass don't share __behavior_token_cache__ ."""
615+ """Parent and subclass don't share __ccflow_tokenizer_cache__ ."""
516616
517617 class Base :
518618 def f (self ):
0 commit comments