2023-12-30 02:37:49 +00:00
|
|
|
import pathlib
|
2024-03-01 03:09:50 +00:00
|
|
|
from dataclasses import dataclass
|
2023-12-30 02:37:49 +00:00
|
|
|
|
2024-05-18 23:41:51 +00:00
|
|
|
import pytest
|
2024-10-29 23:39:47 +00:00
|
|
|
from codeflash.discovery.functions_to_optimize import FunctionToOptimize
|
2024-12-16 23:33:48 +00:00
|
|
|
from codeflash.either import is_successful
|
2024-10-29 23:39:47 +00:00
|
|
|
from codeflash.models.models import FunctionParent
|
2023-12-30 02:37:49 +00:00
|
|
|
from codeflash.optimization.function_context import get_function_variables_definitions
|
2025-02-13 08:10:53 +00:00
|
|
|
from codeflash.optimization.function_optimizer import FunctionOptimizer
|
|
|
|
|
from codeflash.verification.verification_utils import TestConfig
|
2023-12-30 02:37:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_something(data):
|
|
|
|
|
return data + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def simple_function_with_one_dep(data):
|
|
|
|
|
return calculate_something(data)
|
|
|
|
|
|
|
|
|
|
|
2024-06-24 20:53:05 +00:00
|
|
|
def test_simple_dependencies() -> None:
|
2023-12-30 02:37:49 +00:00
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
2024-05-19 02:00:23 +00:00
|
|
|
helper_functions = get_function_variables_definitions(
|
2024-10-25 22:45:44 +00:00
|
|
|
FunctionToOptimize("simple_function_with_one_dep", str(file_path), []), str(file_path.parent.resolve())
|
2024-06-01 04:32:08 +00:00
|
|
|
)[0]
|
2024-05-19 02:00:23 +00:00
|
|
|
assert len(helper_functions) == 1
|
2024-07-06 19:45:11 +00:00
|
|
|
assert helper_functions[0].jedi_definition.full_name == "test_function_dependencies.calculate_something"
|
2023-12-30 02:37:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def global_dependency_1(num):
|
|
|
|
|
return num + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def global_dependency_2(num):
|
|
|
|
|
return num + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def global_dependency_3(num):
|
|
|
|
|
return num + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class A:
|
|
|
|
|
def calculate_something_1(self, num):
|
|
|
|
|
return num + 1
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
a = 1
|
|
|
|
|
b = self.calculate_something_1(a)
|
|
|
|
|
c = global_dependency_1(b)
|
|
|
|
|
return c
|
|
|
|
|
|
2024-12-23 23:27:03 +00:00
|
|
|
def function_in_list_comprehension(self):
|
|
|
|
|
return [global_dependency_3(1) for x in range(10)]
|
|
|
|
|
|
2024-12-26 19:30:29 +00:00
|
|
|
def add_two(self, num):
|
|
|
|
|
return num + 2
|
|
|
|
|
|
2024-12-23 23:27:03 +00:00
|
|
|
def method_in_list_comprehension(self):
|
2024-12-26 19:30:29 +00:00
|
|
|
return [self.add_two(1) for x in range(10)]
|
2024-12-23 23:27:03 +00:00
|
|
|
|
2024-12-26 19:30:29 +00:00
|
|
|
def nested_function(self):
|
|
|
|
|
def nested():
|
|
|
|
|
return global_dependency_3(1)
|
2025-01-08 22:56:53 +00:00
|
|
|
|
2024-12-26 19:30:29 +00:00
|
|
|
return nested() + self.add_two(3)
|
2023-12-30 02:37:49 +00:00
|
|
|
|
2025-01-08 22:56:53 +00:00
|
|
|
|
2023-12-30 02:37:49 +00:00
|
|
|
class B:
|
|
|
|
|
def calculate_something_2(self, num):
|
|
|
|
|
return num + 1
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
a = 1
|
|
|
|
|
b = self.calculate_something_2(a)
|
|
|
|
|
c = global_dependency_2(b)
|
|
|
|
|
return c
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class C:
|
|
|
|
|
def calculate_something_3(self, num):
|
|
|
|
|
return num + 1
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
a = 1
|
|
|
|
|
b = self.calculate_something_3(a)
|
|
|
|
|
c = global_dependency_3(b)
|
|
|
|
|
return c
|
|
|
|
|
|
2024-07-19 01:57:23 +00:00
|
|
|
def recursive(self, num):
|
|
|
|
|
if num == 0:
|
|
|
|
|
return 0
|
|
|
|
|
num_1 = self.calculate_something_3(num)
|
|
|
|
|
return self.recursive(num) + num_1
|
|
|
|
|
|
2023-12-30 02:37:49 +00:00
|
|
|
|
2024-06-24 20:53:05 +00:00
|
|
|
def test_multiple_classes_dependencies() -> None:
|
2023-12-30 02:37:49 +00:00
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
2024-05-19 02:00:23 +00:00
|
|
|
helper_functions = get_function_variables_definitions(
|
2024-10-25 22:45:44 +00:00
|
|
|
FunctionToOptimize("run", str(file_path), [FunctionParent("C", "ClassDef")]), str(file_path.parent.resolve())
|
2024-02-06 08:50:27 +00:00
|
|
|
)
|
2023-12-30 02:37:49 +00:00
|
|
|
|
2024-12-26 19:30:29 +00:00
|
|
|
assert len(helper_functions) == 2
|
2024-07-06 19:45:11 +00:00
|
|
|
assert list(map(lambda x: x.fully_qualified_name, helper_functions[0])) == [
|
2024-05-19 01:15:42 +00:00
|
|
|
"test_function_dependencies.global_dependency_3",
|
2024-06-09 12:30:06 +00:00
|
|
|
"test_function_dependencies.C.calculate_something_3",
|
2023-12-30 02:37:49 +00:00
|
|
|
]
|
2024-01-31 22:53:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def recursive_dependency_1(num):
|
|
|
|
|
if num == 0:
|
|
|
|
|
return 0
|
|
|
|
|
num_1 = calculate_something(num)
|
|
|
|
|
return recursive_dependency_1(num) + num_1
|
|
|
|
|
|
|
|
|
|
|
2024-06-24 20:53:05 +00:00
|
|
|
def test_recursive_dependency() -> None:
|
2024-01-31 22:53:34 +00:00
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
2024-05-19 02:00:23 +00:00
|
|
|
helper_functions = get_function_variables_definitions(
|
2024-10-25 22:45:44 +00:00
|
|
|
FunctionToOptimize("recursive_dependency_1", str(file_path), []), str(file_path.parent.resolve())
|
2024-06-01 04:32:08 +00:00
|
|
|
)[0]
|
2024-05-19 02:00:23 +00:00
|
|
|
assert len(helper_functions) == 1
|
2024-07-06 19:45:11 +00:00
|
|
|
assert helper_functions[0].jedi_definition.full_name == "test_function_dependencies.calculate_something"
|
2024-07-06 22:26:13 +00:00
|
|
|
assert helper_functions[0].fully_qualified_name == "test_function_dependencies.calculate_something"
|
2024-03-01 03:09:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
class MyData:
|
|
|
|
|
MyInt: int
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_something_ann(data):
|
|
|
|
|
return data + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def simple_function_with_one_dep_ann(data: MyData):
|
|
|
|
|
return calculate_something_ann(data)
|
|
|
|
|
|
|
|
|
|
|
2024-12-07 03:34:40 +00:00
|
|
|
def list_comprehension_dependency(data: MyData):
|
|
|
|
|
return [calculate_something(data) for x in range(10)]
|
|
|
|
|
|
|
|
|
|
|
2024-06-24 20:53:05 +00:00
|
|
|
def test_simple_dependencies_ann() -> None:
|
2024-03-01 03:09:50 +00:00
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
2024-05-19 02:00:23 +00:00
|
|
|
helper_functions = get_function_variables_definitions(
|
2024-10-25 22:45:44 +00:00
|
|
|
FunctionToOptimize("simple_function_with_one_dep_ann", str(file_path), []), str(file_path.parent.resolve())
|
2024-06-01 04:32:08 +00:00
|
|
|
)[0]
|
2024-05-19 02:00:23 +00:00
|
|
|
assert len(helper_functions) == 2
|
2024-07-06 19:45:11 +00:00
|
|
|
assert helper_functions[0].jedi_definition.full_name == "test_function_dependencies.MyData"
|
2024-10-25 22:45:44 +00:00
|
|
|
assert helper_functions[1].jedi_definition.full_name == "test_function_dependencies.calculate_something_ann"
|
2024-05-18 23:41:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Graph:
|
|
|
|
|
def __init__(self, vertices):
|
|
|
|
|
self.graph = defaultdict(list)
|
|
|
|
|
self.V = vertices # No. of vertices
|
|
|
|
|
|
|
|
|
|
def addEdge(self, u, v):
|
|
|
|
|
self.graph[u].append(v)
|
|
|
|
|
|
|
|
|
|
def topologicalSortUtil(self, v, visited, stack):
|
|
|
|
|
visited[v] = True
|
|
|
|
|
|
|
|
|
|
for i in self.graph[v]:
|
|
|
|
|
if visited[i] == False:
|
|
|
|
|
self.topologicalSortUtil(i, visited, stack)
|
|
|
|
|
|
|
|
|
|
stack.insert(0, v)
|
|
|
|
|
|
|
|
|
|
def topologicalSort(self):
|
|
|
|
|
visited = [False] * self.V
|
|
|
|
|
stack = []
|
|
|
|
|
|
|
|
|
|
for i in range(self.V):
|
|
|
|
|
if visited[i] == False:
|
|
|
|
|
self.topologicalSortUtil(i, visited, stack)
|
|
|
|
|
|
|
|
|
|
# Print contents of stack
|
|
|
|
|
return stack
|
|
|
|
|
|
|
|
|
|
|
2024-06-24 20:53:05 +00:00
|
|
|
def test_class_method_dependencies() -> None:
|
2024-05-18 23:41:51 +00:00
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
2025-02-13 08:10:53 +00:00
|
|
|
|
2024-05-18 23:41:51 +00:00
|
|
|
function_to_optimize = FunctionToOptimize(
|
|
|
|
|
function_name="topologicalSort",
|
|
|
|
|
file_path=str(file_path),
|
|
|
|
|
parents=[FunctionParent(name="Graph", type="ClassDef")],
|
|
|
|
|
starting_line=None,
|
|
|
|
|
ending_line=None,
|
|
|
|
|
)
|
2025-02-13 08:10:53 +00:00
|
|
|
func_optimizer = FunctionOptimizer(
|
|
|
|
|
function_to_optimize=function_to_optimize,
|
|
|
|
|
test_cfg=TestConfig(
|
|
|
|
|
tests_root=file_path,
|
|
|
|
|
tests_project_rootdir=file_path.parent,
|
|
|
|
|
project_root_path=file_path.parent,
|
|
|
|
|
test_framework="pytest",
|
|
|
|
|
pytest_cmd="pytest",
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-05-18 23:41:51 +00:00
|
|
|
with open(file_path) as f:
|
|
|
|
|
original_code = f.read()
|
2025-02-13 08:10:53 +00:00
|
|
|
ctx_result = func_optimizer.get_code_optimization_context()
|
2024-05-18 23:41:51 +00:00
|
|
|
if not is_successful(ctx_result):
|
|
|
|
|
pytest.fail()
|
|
|
|
|
code_context = ctx_result.unwrap()
|
|
|
|
|
# The code_context above should have the topologicalSortUtil function in it
|
2024-05-19 04:36:15 +00:00
|
|
|
assert len(code_context.helper_functions) == 1
|
|
|
|
|
assert (
|
2024-07-06 19:45:11 +00:00
|
|
|
code_context.helper_functions[0].jedi_definition.full_name
|
2024-05-19 04:36:15 +00:00
|
|
|
== "test_function_dependencies.Graph.topologicalSortUtil"
|
|
|
|
|
)
|
2024-07-06 19:45:11 +00:00
|
|
|
assert code_context.helper_functions[0].jedi_definition.name == "topologicalSortUtil"
|
2024-07-06 22:26:13 +00:00
|
|
|
assert (
|
2024-10-25 22:45:44 +00:00
|
|
|
code_context.helper_functions[0].fully_qualified_name == "test_function_dependencies.Graph.topologicalSortUtil"
|
2024-07-06 22:26:13 +00:00
|
|
|
)
|
2024-07-06 04:06:30 +00:00
|
|
|
assert code_context.helper_functions[0].qualified_name == "Graph.topologicalSortUtil"
|
2024-05-19 04:36:15 +00:00
|
|
|
assert (
|
|
|
|
|
code_context.code_to_optimize_with_helpers
|
|
|
|
|
== """from collections import defaultdict
|
|
|
|
|
|
|
|
|
|
class Graph:
|
|
|
|
|
def __init__(self, vertices):
|
|
|
|
|
self.graph = defaultdict(list)
|
|
|
|
|
self.V = vertices # No. of vertices
|
2024-07-20 01:14:35 +00:00
|
|
|
def topologicalSortUtil(self, v, visited, stack):
|
|
|
|
|
visited[v] = True
|
|
|
|
|
|
|
|
|
|
for i in self.graph[v]:
|
|
|
|
|
if visited[i] == False:
|
|
|
|
|
self.topologicalSortUtil(i, visited, stack)
|
|
|
|
|
|
|
|
|
|
stack.insert(0, v)
|
2024-05-19 04:36:15 +00:00
|
|
|
def topologicalSort(self):
|
|
|
|
|
visited = [False] * self.V
|
|
|
|
|
stack = []
|
|
|
|
|
|
|
|
|
|
for i in range(self.V):
|
|
|
|
|
if visited[i] == False:
|
|
|
|
|
self.topologicalSortUtil(i, visited, stack)
|
|
|
|
|
|
|
|
|
|
# Print contents of stack
|
|
|
|
|
return stack
|
|
|
|
|
"""
|
|
|
|
|
)
|
2024-06-24 20:53:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_something_else(data):
|
|
|
|
|
return data + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def imalittledecorator(func):
|
|
|
|
|
def wrapper(data):
|
|
|
|
|
return func(data)
|
|
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@imalittledecorator
|
|
|
|
|
def simple_function_with_decorator_dep(data):
|
|
|
|
|
return calculate_something_else(data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.skip(reason="no decorator dependency support")
|
|
|
|
|
def test_decorator_dependencies() -> None:
|
|
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
|
|
|
|
helper_functions = get_function_variables_definitions(
|
2024-10-25 22:45:44 +00:00
|
|
|
FunctionToOptimize("simple_function_with_decorator_dep", str(file_path), []), str(file_path.parent.resolve())
|
2024-06-24 20:53:05 +00:00
|
|
|
)[0]
|
|
|
|
|
assert len(helper_functions) == 2
|
|
|
|
|
assert {helper_functions[0][0].definition.full_name, helper_functions[1][0].definition.full_name} == {
|
|
|
|
|
"test_function_dependencies.calculate_something",
|
|
|
|
|
"test_function_dependencies.imalittledecorator",
|
|
|
|
|
}
|
2024-07-19 01:57:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_recursive_function_context() -> None:
|
|
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
2025-02-13 08:10:53 +00:00
|
|
|
|
2024-07-19 01:57:23 +00:00
|
|
|
function_to_optimize = FunctionToOptimize(
|
|
|
|
|
function_name="recursive",
|
|
|
|
|
file_path=str(file_path),
|
|
|
|
|
parents=[FunctionParent(name="C", type="ClassDef")],
|
|
|
|
|
starting_line=None,
|
|
|
|
|
ending_line=None,
|
|
|
|
|
)
|
2025-02-13 08:10:53 +00:00
|
|
|
func_optimizer = FunctionOptimizer(
|
|
|
|
|
function_to_optimize=function_to_optimize,
|
|
|
|
|
test_cfg=TestConfig(
|
|
|
|
|
tests_root=file_path,
|
|
|
|
|
tests_project_rootdir=file_path.parent,
|
|
|
|
|
project_root_path=file_path.parent,
|
|
|
|
|
test_framework="pytest",
|
|
|
|
|
pytest_cmd="pytest",
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-07-19 01:57:23 +00:00
|
|
|
with open(file_path) as f:
|
|
|
|
|
original_code = f.read()
|
2025-02-13 08:10:53 +00:00
|
|
|
|
|
|
|
|
ctx_result = func_optimizer.get_code_optimization_context()
|
2024-07-19 01:57:23 +00:00
|
|
|
if not is_successful(ctx_result):
|
|
|
|
|
pytest.fail()
|
|
|
|
|
code_context = ctx_result.unwrap()
|
2025-01-08 22:56:53 +00:00
|
|
|
assert len(code_context.helper_functions) == 2
|
2024-12-26 19:30:29 +00:00
|
|
|
assert code_context.helper_functions[0].fully_qualified_name == "test_function_dependencies.C.calculate_something_3"
|
2025-01-08 22:56:53 +00:00
|
|
|
assert code_context.helper_functions[1].fully_qualified_name == "test_function_dependencies.C.recursive"
|
2024-07-19 01:57:23 +00:00
|
|
|
assert (
|
|
|
|
|
code_context.code_to_optimize_with_helpers
|
|
|
|
|
== """class C:
|
2024-07-20 01:14:35 +00:00
|
|
|
def calculate_something_3(self, num):
|
|
|
|
|
return num + 1
|
2024-07-19 01:57:23 +00:00
|
|
|
def recursive(self, num):
|
|
|
|
|
if num == 0:
|
|
|
|
|
return 0
|
|
|
|
|
num_1 = self.calculate_something_3(num)
|
|
|
|
|
return self.recursive(num) + num_1
|
|
|
|
|
"""
|
|
|
|
|
)
|
2024-12-07 03:34:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_list_comprehension_dependency() -> None:
|
|
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
|
|
|
|
helper_functions = get_function_variables_definitions(
|
|
|
|
|
FunctionToOptimize("list_comprehension_dependency", str(file_path), []), str(file_path.parent.resolve())
|
|
|
|
|
)[0]
|
|
|
|
|
assert len(helper_functions) == 2
|
|
|
|
|
assert helper_functions[0].jedi_definition.full_name == "test_function_dependencies.MyData"
|
|
|
|
|
assert helper_functions[1].jedi_definition.full_name == "test_function_dependencies.calculate_something"
|
2024-12-23 23:27:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_function_in_method_list_comprehension() -> None:
|
|
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
|
|
|
|
function_to_optimize = FunctionToOptimize(
|
|
|
|
|
function_name="function_in_list_comprehension",
|
|
|
|
|
file_path=str(file_path),
|
|
|
|
|
parents=[FunctionParent(name="A", type="ClassDef")],
|
|
|
|
|
starting_line=None,
|
|
|
|
|
ending_line=None,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
helper_functions = get_function_variables_definitions(function_to_optimize, str(file_path.parent.resolve()))[0]
|
|
|
|
|
|
|
|
|
|
assert len(helper_functions) == 1
|
|
|
|
|
assert helper_functions[0].jedi_definition.full_name == "test_function_dependencies.global_dependency_3"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_method_in_method_list_comprehension() -> None:
|
|
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
|
|
|
|
function_to_optimize = FunctionToOptimize(
|
|
|
|
|
function_name="method_in_list_comprehension",
|
|
|
|
|
file_path=str(file_path),
|
|
|
|
|
parents=[FunctionParent(name="A", type="ClassDef")],
|
|
|
|
|
starting_line=None,
|
|
|
|
|
ending_line=None,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
helper_functions = get_function_variables_definitions(function_to_optimize, str(file_path.parent.resolve()))[0]
|
|
|
|
|
|
|
|
|
|
assert len(helper_functions) == 1
|
2024-12-26 19:30:29 +00:00
|
|
|
assert helper_functions[0].jedi_definition.full_name == "test_function_dependencies.A.add_two"
|
|
|
|
|
|
2025-01-08 22:56:53 +00:00
|
|
|
|
2024-12-26 19:30:29 +00:00
|
|
|
def test_nested_method() -> None:
|
|
|
|
|
file_path = pathlib.Path(__file__).resolve()
|
|
|
|
|
function_to_optimize = FunctionToOptimize(
|
|
|
|
|
function_name="nested_function",
|
|
|
|
|
file_path=str(file_path),
|
|
|
|
|
parents=[FunctionParent(name="A", type="ClassDef")],
|
|
|
|
|
starting_line=None,
|
|
|
|
|
ending_line=None,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
helper_functions = get_function_variables_definitions(function_to_optimize, str(file_path.parent.resolve()))[0]
|
|
|
|
|
|
|
|
|
|
# The nested function should be included in the helper functions
|
|
|
|
|
assert len(helper_functions) == 1
|
|
|
|
|
assert helper_functions[0].jedi_definition.full_name == "test_function_dependencies.A.add_two"
|