speedy-utils 1.1.25__tar.gz → 1.1.27__tar.gz

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.
Files changed (81) hide show
  1. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/PKG-INFO +1 -1
  2. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/bumpversion.sh +1 -1
  3. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/pyproject.toml +1 -1
  4. speedy_utils-1.1.25/debug_imemoize.py +0 -66
  5. speedy_utils-1.1.25/debug_imemoize_flow.py +0 -95
  6. speedy_utils-1.1.25/test_imemoize.py +0 -116
  7. speedy_utils-1.1.25/test_imemoize_persistence.py +0 -122
  8. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/.github/copilot-instructions.md +0 -0
  9. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/.github/workflows/publish.yml +0 -0
  10. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/.gitignore +0 -0
  11. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/.pre-commit-config.yaml +0 -0
  12. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/IMPROVEMENTS.md +0 -0
  13. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/README.md +0 -0
  14. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/examples/temperature_range_example.py +0 -0
  15. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/examples_improved_error_tracing.py +0 -0
  16. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/notebooks/llm_utils/llm_as_a_judge.ipynb +0 -0
  17. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/notebooks/test_multi_thread.ipynb +0 -0
  18. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/ruff.toml +0 -0
  19. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/scripts/deploy.sh +0 -0
  20. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/setup.cfg +0 -0
  21. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/simple_test_imemoize.py +0 -0
  22. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/__init__.py +0 -0
  23. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/chat_format/__init__.py +0 -0
  24. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/chat_format/display.py +0 -0
  25. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/chat_format/transform.py +0 -0
  26. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/chat_format/utils.py +0 -0
  27. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/group_messages.py +0 -0
  28. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/__init__.py +0 -0
  29. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/async_lm/__init__.py +0 -0
  30. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/async_lm/_utils.py +0 -0
  31. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/async_lm/async_llm_task.py +0 -0
  32. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/async_lm/async_lm.py +0 -0
  33. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/async_lm/async_lm_base.py +0 -0
  34. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/async_lm/lm_specific.py +0 -0
  35. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/base_prompt_builder.py +0 -0
  36. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/llm.py +0 -0
  37. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/llm_signature.py +0 -0
  38. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/lm_base.py +0 -0
  39. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/mixins.py +0 -0
  40. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/openai_memoize.py +0 -0
  41. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/signature.py +0 -0
  42. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/lm/utils.py +0 -0
  43. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/scripts/README.md +0 -0
  44. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/scripts/vllm_load_balancer.py +0 -0
  45. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/scripts/vllm_serve.py +0 -0
  46. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/vector_cache/__init__.py +0 -0
  47. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/vector_cache/cli.py +0 -0
  48. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/vector_cache/core.py +0 -0
  49. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/vector_cache/types.py +0 -0
  50. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/llm_utils/vector_cache/utils.py +0 -0
  51. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/__init__.py +0 -0
  52. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/all.py +0 -0
  53. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/__init__.py +0 -0
  54. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/clock.py +0 -0
  55. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/function_decorator.py +0 -0
  56. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/logger.py +0 -0
  57. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/notebook_utils.py +0 -0
  58. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/patcher.py +0 -0
  59. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/report_manager.py +0 -0
  60. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/utils_cache.py +0 -0
  61. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/utils_io.py +0 -0
  62. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/utils_misc.py +0 -0
  63. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/common/utils_print.py +0 -0
  64. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/multi_worker/__init__.py +0 -0
  65. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/multi_worker/process.py +0 -0
  66. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/multi_worker/thread.py +0 -0
  67. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/scripts/__init__.py +0 -0
  68. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/scripts/mpython.py +0 -0
  69. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/src/speedy_utils/scripts/openapi_client_codegen.py +0 -0
  70. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/llm_utils/test_llm_mixins.py +0 -0
  71. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/sample_objects.py +0 -0
  72. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test.py +0 -0
  73. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_logger.py +0 -0
  74. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_logger_format.py +0 -0
  75. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_memoize_typing.py +0 -0
  76. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_mpython.py +0 -0
  77. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_multithread_error_trace.py +0 -0
  78. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_process.py +0 -0
  79. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_process_update.py +0 -0
  80. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/tests/test_thread.py +0 -0
  81. {speedy_utils-1.1.25 → speedy_utils-1.1.27}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: speedy-utils
3
- Version: 1.1.25
3
+ Version: 1.1.27
4
4
  Summary: Fast and easy-to-use package for data science
5
5
  Project-URL: Homepage, https://github.com/anhvth/speedy
6
6
  Project-URL: Repository, https://github.com/anhvth/speedy
@@ -1,7 +1,7 @@
1
1
  #!/bin/zsh
2
2
  # Bump patch version using poetry, commit, and push
3
3
  set -e
4
-
4
+ uv pip install poetry
5
5
  echo 'Current version:'
6
6
  poetry version
7
7
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "speedy-utils"
3
- version = "1.1.25"
3
+ version = "1.1.27"
4
4
  description = "Fast and easy-to-use package for data science"
5
5
  authors = [{ name = "AnhVTH", email = "anhvth.226@gmail.com" }]
6
6
  readme = "README.md"
@@ -1,66 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Debug the imemoize cache key generation
4
- """
5
-
6
- import sys
7
- import time
8
- import os.path as osp
9
- sys.path.insert(0, osp.join(osp.dirname(__file__), 'src'))
10
-
11
- from speedy_utils.common.utils_cache import imemoize, _GLOBAL_MEMORY_CACHE, get_source, identify, _compute_cache_components
12
-
13
- def debug_cache_keys():
14
- """Debug what cache keys are generated"""
15
- print("=== Debugging cache key generation ===")
16
-
17
- # Clear cache
18
- _GLOBAL_MEMORY_CACHE.clear()
19
-
20
- # First function
21
- @imemoize
22
- def test_func(x):
23
- return x * x
24
-
25
- # Get cache components
26
- func_source1, sub_dir1, key_id1 = _compute_cache_components(
27
- test_func, (5,), {}, True, None, None
28
- )
29
- cache_key1 = identify((func_source1, sub_dir1, key_id1))
30
-
31
- print(f"Function 1 source length: {len(func_source1)}")
32
- print(f"Function 1 source: {func_source1[:100]}...")
33
- print(f"Function 1 cache key: {cache_key1}")
34
-
35
- # Call function
36
- result1 = test_func(5)
37
- print(f"After call 1, cache size: {len(_GLOBAL_MEMORY_CACHE)}")
38
-
39
- # Redefine same function
40
- @imemoize
41
- def test_func(x):
42
- return x * x
43
-
44
- # Get cache components for redefined function
45
- func_source2, sub_dir2, key_id2 = _compute_cache_components(
46
- test_func, (5,), {}, True, None, None
47
- )
48
- cache_key2 = identify((func_source2, sub_dir2, key_id2))
49
-
50
- print(f"\nFunction 2 source length: {len(func_source2)}")
51
- print(f"Function 2 source: {func_source2[:100]}...")
52
- print(f"Function 2 cache key: {cache_key2}")
53
-
54
- print(f"\nSource code same: {func_source1 == func_source2}")
55
- print(f"Cache keys same: {cache_key1 == cache_key2}")
56
-
57
- # Call function again
58
- result2 = test_func(5)
59
- print(f"After call 2, cache size: {len(_GLOBAL_MEMORY_CACHE)}")
60
-
61
- print(f"\nCache contents:")
62
- for i, (key, value) in enumerate(_GLOBAL_MEMORY_CACHE.items()):
63
- print(f" {i+1}. {key[:50]}... -> {value}")
64
-
65
- if __name__ == "__main__":
66
- debug_cache_keys()
@@ -1,95 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Debug the imemoize execution flow
4
- """
5
-
6
- import sys
7
- import time
8
- import os.path as osp
9
- sys.path.insert(0, osp.join(osp.dirname(__file__), 'src'))
10
-
11
- from speedy_utils.common.utils_cache import _GLOBAL_MEMORY_CACHE, identify, _compute_cache_components
12
- from speedy_utils.common.utils_cache import mem_lock
13
-
14
- def create_debug_imemoize():
15
- """Create a debug version of imemoize with detailed logging"""
16
- import functools
17
- import inspect
18
-
19
- def debug_imemoize(func):
20
- print(f"Creating imemoize wrapper for {func.__name__}")
21
-
22
- @functools.wraps(func)
23
- def wrapper(*args, **kwargs):
24
- print(f"\n--- Calling {func.__name__}({args}, {kwargs}) ---")
25
-
26
- # Compute cache key
27
- func_source, sub_dir, key_id = _compute_cache_components(
28
- func, args, kwargs, True, None, None
29
- )
30
- cache_key = identify((func_source, sub_dir, key_id))
31
-
32
- print(f"Function source: {func_source[:50]}...")
33
- print(f"Cache key: {cache_key}")
34
- print(f"Cache size before lookup: {len(_GLOBAL_MEMORY_CACHE)}")
35
-
36
- # Check cache
37
- with mem_lock:
38
- if cache_key in _GLOBAL_MEMORY_CACHE:
39
- cached_result = _GLOBAL_MEMORY_CACHE[cache_key]
40
- print(f"CACHE HIT: Found {cached_result}")
41
- return cached_result
42
- else:
43
- print(f"CACHE MISS: Key not found")
44
- print(f"Available keys:")
45
- for i, key in enumerate(_GLOBAL_MEMORY_CACHE.keys()):
46
- print(f" {i+1}. {key}")
47
-
48
- # Compute result
49
- print(f"Computing result...")
50
- start = time.time()
51
- result = func(*args, **kwargs)
52
- end = time.time()
53
- print(f"Computation took {end - start:.6f}s")
54
-
55
- # Store in cache
56
- with mem_lock:
57
- _GLOBAL_MEMORY_CACHE[cache_key] = result
58
- print(f"Stored result in cache. Cache size now: {len(_GLOBAL_MEMORY_CACHE)}")
59
-
60
- return result
61
-
62
- return wrapper
63
-
64
- return debug_imemoize
65
-
66
- def test_debug():
67
- debug_imemoize = create_debug_imemoize()
68
-
69
- # Clear cache
70
- _GLOBAL_MEMORY_CACHE.clear()
71
- print("Cache cleared")
72
-
73
- # First function
74
- @debug_imemoize
75
- def test_func(x):
76
- time.sleep(0.05)
77
- return x * x
78
-
79
- print("\n=== FIRST CALL ===")
80
- result1 = test_func(5)
81
-
82
- print("\n=== SECOND CALL (same function object) ===")
83
- result2 = test_func(5)
84
-
85
- # Redefine function
86
- @debug_imemoize
87
- def test_func(x):
88
- time.sleep(0.05)
89
- return x * x
90
-
91
- print("\n=== THIRD CALL (new function object, same source) ===")
92
- result3 = test_func(5)
93
-
94
- if __name__ == "__main__":
95
- test_debug()
@@ -1,116 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Test script for imemoize functionality
4
- """
5
-
6
- import sys
7
- import time
8
- sys.path.insert(0, 'src')
9
-
10
- from speedy_utils import imemoize
11
-
12
- @imemoize
13
- def expensive_computation(x, y=1):
14
- """Simulate an expensive computation"""
15
- print(f"Computing expensive_computation({x}, {y})")
16
- time.sleep(0.1) # Simulate work
17
- return x * x + y
18
-
19
- @imemoize
20
- async def async_expensive_computation(x):
21
- """Simulate an expensive async computation"""
22
- import asyncio
23
- print(f"Computing async_expensive_computation({x})")
24
- await asyncio.sleep(0.1) # Simulate work
25
- return x * x
26
-
27
- def test_basic_functionality():
28
- print("=== Testing basic functionality ===")
29
-
30
- # Test sync function
31
- print("First call:")
32
- start = time.time()
33
- result1 = expensive_computation(5)
34
- end = time.time()
35
- print(f"Result: {result1}, Time: {end - start:.3f}s")
36
-
37
- print("Second call (should be cached):")
38
- start = time.time()
39
- result2 = expensive_computation(5)
40
- end = time.time()
41
- print(f"Result: {result2}, Time: {end - start:.3f}s")
42
-
43
- assert result1 == result2
44
- print("✓ Basic sync caching works")
45
-
46
- def test_different_arguments():
47
- print("\n=== Testing different arguments ===")
48
-
49
- # Different arguments should compute separately
50
- result1 = expensive_computation(3)
51
- result2 = expensive_computation(4)
52
- result3 = expensive_computation(3, y=2) # Different y value
53
- result4 = expensive_computation(3) # Should be cached
54
-
55
- print(f"expensive_computation(3) = {result1}")
56
- print(f"expensive_computation(4) = {result2}")
57
- print(f"expensive_computation(3, y=2) = {result3}")
58
- print(f"expensive_computation(3) again = {result4}")
59
-
60
- assert result1 != result2
61
- assert result1 != result3
62
- assert result1 == result4
63
- print("✓ Different arguments work correctly")
64
-
65
- async def test_async_functionality():
66
- print("\n=== Testing async functionality ===")
67
-
68
- start = time.time()
69
- result1 = await async_expensive_computation(7)
70
- end = time.time()
71
- print(f"First async call: {result1}, Time: {end - start:.3f}s")
72
-
73
- start = time.time()
74
- result2 = await async_expensive_computation(7)
75
- end = time.time()
76
- print(f"Second async call (cached): {result2}, Time: {end - start:.3f}s")
77
-
78
- assert result1 == result2
79
- print("✓ Async caching works")
80
-
81
- def test_code_change_detection():
82
- print("\n=== Testing code change detection ===")
83
-
84
- # Create a function dynamically to simulate code changes
85
- def create_function(multiplier):
86
- @imemoize
87
- def dynamic_func(x):
88
- print(f"Computing with multiplier {multiplier}")
89
- return x * multiplier
90
- return dynamic_func
91
-
92
- func1 = create_function(2)
93
- func2 = create_function(3)
94
-
95
- result1a = func1(5) # Should compute
96
- result1b = func1(5) # Should be cached
97
- result2a = func2(5) # Different function, should compute
98
-
99
- print(f"func1(5) first: {result1a}")
100
- print(f"func1(5) second: {result1b}")
101
- print(f"func2(5): {result2a}")
102
-
103
- assert result1a == result1b == 10
104
- assert result2a == 15
105
- print("✓ Code change detection works")
106
-
107
- if __name__ == "__main__":
108
- test_basic_functionality()
109
- test_different_arguments()
110
-
111
- import asyncio
112
- asyncio.run(test_async_functionality())
113
-
114
- test_code_change_detection()
115
-
116
- print("\n🎉 All tests passed!")
@@ -1,122 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Test imemoize persistence across function redefinition (simulating IPython reload)
4
- """
5
-
6
- import sys
7
- import time
8
- import os.path as osp
9
- sys.path.insert(0, osp.join(osp.dirname(__file__), 'src'))
10
-
11
- from speedy_utils.common.utils_cache import imemoize, _GLOBAL_MEMORY_CACHE
12
-
13
- def test_ipython_reload_simulation():
14
- """
15
- Test that imemoize persists across function redefinition,
16
- simulating what happens in IPython when %load is used
17
- """
18
- print("=== Testing IPython reload simulation ===")
19
-
20
- # Clear any existing cache
21
- _GLOBAL_MEMORY_CACHE.clear()
22
-
23
- # First definition of the function
24
- @imemoize
25
- def computation_v1(x):
26
- print(f"Computing v1({x})")
27
- time.sleep(0.05)
28
- return x * x
29
-
30
- # Call it first time
31
- print("1. First call to v1:")
32
- result1 = computation_v1(10)
33
- print(f" Result: {result1}")
34
-
35
- # Call it second time (should be cached)
36
- print("2. Second call to v1 (should be cached):")
37
- start = time.time()
38
- result2 = computation_v1(10)
39
- end = time.time()
40
- print(f" Result: {result2}, Time: {end - start:.6f}s")
41
-
42
- assert result1 == result2
43
- assert end - start < 0.01 # Should be very fast (cached)
44
-
45
- # Check cache has content
46
- print(f"3. Cache now contains {len(_GLOBAL_MEMORY_CACHE)} entries")
47
-
48
- # Now simulate IPython %load - redefine the SAME function
49
- @imemoize
50
- def computation_v1(x): # Same name, same logic
51
- print(f"Computing v1({x})")
52
- time.sleep(0.05)
53
- return x * x
54
-
55
- # This should still be cached because source code is the same
56
- print("4. Call after 'reload' with same code (should be cached):")
57
- start = time.time()
58
- result3 = computation_v1(10)
59
- end = time.time()
60
- print(f" Result: {result3}, Time: {end - start:.6f}s")
61
-
62
- assert result3 == result1
63
- assert end - start < 0.01 # Should still be fast (cached)
64
-
65
- # Now simulate a code change
66
- @imemoize
67
- def computation_v1(x): # Same name, different logic
68
- print(f"Computing v1 modified({x})")
69
- time.sleep(0.05)
70
- return x * x * 2 # Different computation!
71
-
72
- # This should NOT be cached because source code changed
73
- print("5. Call after code change (should NOT be cached):")
74
- start = time.time()
75
- result4 = computation_v1(10)
76
- end = time.time()
77
- print(f" Result: {result4}, Time: {end - start:.3f}s")
78
-
79
- assert result4 == 200 # New computation
80
- assert result4 != result1 # Different from before
81
- assert end - start > 0.04 # Should be slow (not cached)
82
-
83
- # Second call to modified function should now be cached
84
- print("6. Second call to modified function (should be cached):")
85
- start = time.time()
86
- result5 = computation_v1(10)
87
- end = time.time()
88
- print(f" Result: {result5}, Time: {end - start:.6f}s")
89
-
90
- assert result5 == result4
91
- assert end - start < 0.01 # Should be fast (cached)
92
-
93
- print("✓ IPython reload simulation works correctly!")
94
-
95
- def test_cross_function_caching():
96
- """Test that different functions have separate cache entries"""
97
- print("\n=== Testing cross-function caching ===")
98
-
99
- @imemoize
100
- def func_a(x):
101
- print(f"Computing func_a({x})")
102
- return x + 1
103
-
104
- @imemoize
105
- def func_b(x):
106
- print(f"Computing func_b({x})")
107
- return x + 1 # Same logic, different function
108
-
109
- # Both should compute independently
110
- result_a = func_a(5)
111
- result_b = func_b(5)
112
-
113
- print(f"func_a(5) = {result_a}")
114
- print(f"func_b(5) = {result_b}")
115
-
116
- assert result_a == result_b == 6
117
- print("✓ Different functions cache independently!")
118
-
119
- if __name__ == "__main__":
120
- test_ipython_reload_simulation()
121
- test_cross_function_caching()
122
- print("\n🎉 All persistence tests passed!")
File without changes
File without changes
File without changes
File without changes
File without changes