Skip to content

Commit 8b90050

Browse files
authored
Merge pull request #1411 from codeflash-ai/init_caching
init caching enabled by instrumenting @codeflash_capture on __init__ [CF-496]
2 parents ad4c323 + d58e21a commit 8b90050

27 files changed

+3426
-315
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class BubbleSorter:
2+
def __init__(self, x=0):
3+
self.x = x
4+
5+
def sorter(self, arr):
6+
for i in range(len(arr)):
7+
for j in range(len(arr) - 1):
8+
if arr[j] > arr[j + 1]:
9+
temp = arr[j]
10+
arr[j] = arr[j + 1]
11+
arr[j + 1] = temp
12+
return arr
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import re
2+
3+
4+
class CharacterRemover:
5+
def __init__(self):
6+
self.version = "0.1"
7+
8+
def remove_control_characters(self, s) -> str:
9+
"""Remove control characters from the string."""
10+
return re.sub("[\\x00-\\x1F\\x7F]", "", s) if s else ""

code_to_optimize/text_processor.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
class TextProcessor:
2+
def __init__(self):
3+
self.version = "0.1"
4+
5+
def find_unique_words(self, text):
6+
stop_words = {
7+
"a",
8+
"about",
9+
"above",
10+
"after",
11+
"again",
12+
"against",
13+
"ain",
14+
"all",
15+
"am",
16+
"an",
17+
"and",
18+
"any",
19+
"are",
20+
"aren",
21+
"aren't",
22+
"as",
23+
"at",
24+
"be",
25+
"because",
26+
"been",
27+
"before",
28+
"being",
29+
"below",
30+
"between",
31+
"both",
32+
"but",
33+
"by",
34+
"can",
35+
"couldn",
36+
"couldn't",
37+
"did",
38+
"didn",
39+
"didn't",
40+
"do",
41+
"does",
42+
"doesn",
43+
"doesn't",
44+
"doing",
45+
"don",
46+
"don't",
47+
"down",
48+
"during",
49+
"each",
50+
"few",
51+
"for",
52+
"from",
53+
"further",
54+
"had",
55+
"hadn",
56+
"hadn't",
57+
"has",
58+
"hasn",
59+
"hasn't",
60+
"have",
61+
"haven",
62+
"haven't",
63+
"having",
64+
"he",
65+
"her",
66+
"here",
67+
"hers",
68+
"herself",
69+
"him",
70+
"himself",
71+
"his",
72+
"how",
73+
"i",
74+
"if",
75+
"in",
76+
"into",
77+
"is",
78+
"isn",
79+
"isn't",
80+
"it",
81+
"it's",
82+
"its",
83+
"itself",
84+
"just",
85+
"ll",
86+
"let's",
87+
"ma",
88+
"me",
89+
"mightn",
90+
"mightn't",
91+
"more",
92+
"most",
93+
"mustn",
94+
"mustn't",
95+
"my",
96+
"myself",
97+
"needn",
98+
"needn't",
99+
"no",
100+
"nor",
101+
"not",
102+
"now",
103+
"o",
104+
"of",
105+
"off",
106+
"on",
107+
"once",
108+
"only",
109+
"or",
110+
"other",
111+
"our",
112+
"ours",
113+
"ourselves",
114+
"out",
115+
"over",
116+
"own",
117+
"re",
118+
"s",
119+
"same",
120+
"shan",
121+
"shan't",
122+
"she",
123+
"she's",
124+
"should",
125+
"should've",
126+
"shouldn",
127+
"shouldn't",
128+
"so",
129+
"some",
130+
"such",
131+
"t",
132+
"than",
133+
"that",
134+
"that'll",
135+
"the",
136+
"their",
137+
"theirs",
138+
"them",
139+
"themselves",
140+
"then",
141+
"there",
142+
"these",
143+
"they",
144+
"this",
145+
"those",
146+
"through",
147+
"to",
148+
"too",
149+
"under",
150+
"until",
151+
"up",
152+
"ve",
153+
"very",
154+
"was",
155+
"wasn",
156+
"wasn't",
157+
"we",
158+
"were",
159+
"weren",
160+
"weren't",
161+
"what",
162+
"when",
163+
"where",
164+
"which",
165+
"while",
166+
"who",
167+
"whom",
168+
"why",
169+
"will",
170+
"with",
171+
"won",
172+
"won't",
173+
"wouldn",
174+
"wouldn't",
175+
"y",
176+
"you",
177+
"you'd",
178+
"you'll",
179+
"you're",
180+
"you've",
181+
"your",
182+
"yours",
183+
"yourself",
184+
"yourselves",
185+
}
186+
187+
words = text.lower().split()
188+
unique_words = [word for word in words if word not in stop_words]
189+
190+
return unique_words

codeflash/code_utils/code_replacer.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@ def __init__(
5151
self.new_functions: list[cst.FunctionDef] = []
5252
self.new_class_functions: dict[str, list[cst.FunctionDef]] = defaultdict(list)
5353
self.current_class = None
54+
self.modified_init_functions: dict[str, cst.FunctionDef] = {}
5455

5556
def visit_FunctionDef(self, node: cst.FunctionDef) -> bool:
5657
if (self.current_class, node.name.value) in self.function_names:
5758
self.modified_functions[(self.current_class, node.name.value)] = node
59+
elif self.current_class and node.name.value == "__init__":
60+
self.modified_init_functions[self.current_class] = node
5861
elif (
5962
self.preexisting_objects
6063
and (node.name.value, []) not in self.preexisting_objects
@@ -76,6 +79,7 @@ def visit_ClassDef(self, node: cst.ClassDef) -> bool:
7679
and (child_node.name.value, parents) not in self.preexisting_objects
7780
):
7881
self.new_class_functions[node.name.value].append(child_node)
82+
7983
return True
8084

8185
def leave_ClassDef(self, node: cst.ClassDef) -> None:
@@ -89,11 +93,15 @@ def __init__(
8993
modified_functions: dict[tuple[str | None, str], cst.FunctionDef] = None,
9094
new_functions: list[cst.FunctionDef] = None,
9195
new_class_functions: dict[str, list[cst.FunctionDef]] = None,
96+
modified_init_functions: dict[str, cst.FunctionDef] = None,
9297
) -> None:
9398
super().__init__()
9499
self.modified_functions = modified_functions if modified_functions is not None else {}
95100
self.new_functions = new_functions if new_functions is not None else []
96101
self.new_class_functions = new_class_functions if new_class_functions is not None else defaultdict(list)
102+
self.modified_init_functions: dict[str, cst.FunctionDef] = (
103+
modified_init_functions if modified_init_functions is not None else {}
104+
)
97105
self.current_class = None
98106

99107
def visit_FunctionDef(self, node: cst.FunctionDef) -> bool:
@@ -103,6 +111,8 @@ def leave_FunctionDef(self, original_node: cst.FunctionDef, updated_node: cst.Fu
103111
if (self.current_class, original_node.name.value) in self.modified_functions:
104112
node = self.modified_functions[(self.current_class, original_node.name.value)]
105113
return updated_node.with_changes(body=node.body, decorators=node.decorators)
114+
if original_node.name.value == "__init__" and self.current_class in self.modified_init_functions:
115+
return self.modified_init_functions[self.current_class]
106116

107117
return updated_node
108118

@@ -173,6 +183,7 @@ def replace_functions_in_file(
173183
modified_functions=visitor.modified_functions,
174184
new_functions=visitor.new_functions,
175185
new_class_functions=visitor.new_class_functions,
186+
modified_init_functions=visitor.modified_init_functions,
176187
)
177188
original_module = cst.parse_module(source_code)
178189
modified_tree = original_module.visit(transformer)
@@ -183,15 +194,14 @@ def replace_functions_and_add_imports(
183194
source_code: str,
184195
function_names: list[str],
185196
optimized_code: str,
186-
file_path_of_module_with_function_to_optimize: Path,
187197
module_abspath: Path,
188198
preexisting_objects: list[tuple[str, list[FunctionParent]]],
189199
project_root_path: Path,
190200
) -> str:
191201
return add_needed_imports_from_module(
192202
optimized_code,
193203
replace_functions_in_file(source_code, function_names, optimized_code, preexisting_objects),
194-
file_path_of_module_with_function_to_optimize,
204+
module_abspath,
195205
module_abspath,
196206
project_root_path,
197207
)
@@ -200,20 +210,13 @@ def replace_functions_and_add_imports(
200210
def replace_function_definitions_in_module(
201211
function_names: list[str],
202212
optimized_code: str,
203-
file_path_of_module_with_function_to_optimize: Path,
204213
module_abspath: Path,
205214
preexisting_objects: list[tuple[str, list[FunctionParent]]],
206215
project_root_path: Path,
207216
) -> bool:
208217
source_code: str = module_abspath.read_text(encoding="utf8")
209218
new_code: str = replace_functions_and_add_imports(
210-
source_code,
211-
function_names,
212-
optimized_code,
213-
file_path_of_module_with_function_to_optimize,
214-
module_abspath,
215-
preexisting_objects,
216-
project_root_path,
219+
source_code, function_names, optimized_code, module_abspath, preexisting_objects, project_root_path
217220
)
218221
if is_zero_diff(source_code, new_code):
219222
return False

codeflash/code_utils/instrument_existing_tests.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from codeflash.code_utils.code_utils import get_run_tmp_file, module_name_from_file_path
1111
from codeflash.discovery.functions_to_optimize import FunctionToOptimize
1212
from codeflash.models.models import FunctionParent, TestingMode
13+
from codeflash.verification.test_results import VerificationType
1314

1415
if TYPE_CHECKING:
1516
from collections.abc import Iterable
@@ -251,7 +252,7 @@ def visit_FunctionDef(self, node: ast.FunctionDef, test_class_name: str | None =
251252
ast.Constant(
252253
value="CREATE TABLE IF NOT EXISTS test_results (test_module_path TEXT,"
253254
" test_class_name TEXT, test_function_name TEXT, function_getting_tested TEXT,"
254-
" loop_index INTEGER, iteration_id TEXT, runtime INTEGER, return_value BLOB)"
255+
" loop_index INTEGER, iteration_id TEXT, runtime INTEGER, return_value BLOB, verification_type TEXT)"
255256
)
256257
],
257258
keywords=[],
@@ -684,7 +685,7 @@ def create_wrapper_function(mode: TestingMode = TestingMode.BEHAVIOR) -> ast.Fun
684685
value=ast.Name(id="codeflash_cur", ctx=ast.Load()), attr="execute", ctx=ast.Load()
685686
),
686687
args=[
687-
ast.Constant(value="INSERT INTO test_results VALUES (?, ?, ?, ?, ?, ?, ?, ?)"),
688+
ast.Constant(value="INSERT INTO test_results VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"),
688689
ast.Tuple(
689690
elts=[
690691
ast.Name(id="test_module_name", ctx=ast.Load()),
@@ -695,6 +696,7 @@ def create_wrapper_function(mode: TestingMode = TestingMode.BEHAVIOR) -> ast.Fun
695696
ast.Name(id="invocation_id", ctx=ast.Load()),
696697
ast.Name(id="codeflash_duration", ctx=ast.Load()),
697698
ast.Name(id="pickled_return_value", ctx=ast.Load()),
699+
ast.Constant(value=VerificationType.FUNCTION_CALL.value),
698700
],
699701
ctx=ast.Load(),
700702
),

0 commit comments

Comments
 (0)