mirror of
https://github.com/Significant-Gravitas/AutoGPT-Code-Ability.git
synced 2026-11-10 08:01:27 -10:00
Merge branch 'main' into ntindle/agpt-401-add-codex-client-to-manage-all-codex-state-in-discord-bot
This commit is contained in:
7 files changed
+448
-33
No files matched your search
@@ -2,6 +2,7 @@ import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from prisma.enums import FunctionState
|
||||
from prisma.models import APIRouteSpec, CompletedApp, Function, Specification
|
||||
|
||||
from codex.api_model import Identifiers
|
||||
@@ -78,7 +79,7 @@ async def develop_route(
|
||||
invoke_params={
|
||||
"function_name": function_name,
|
||||
"goal": goal_description,
|
||||
"description": function_template or "",
|
||||
"function_signature": function_template,
|
||||
"provided_functions": [
|
||||
f.template
|
||||
for f in generated_functions
|
||||
@@ -107,6 +108,7 @@ async def develop_route(
|
||||
generated_functions=generated_functions,
|
||||
)
|
||||
for child in route_function.ChildFunction
|
||||
if child.state == FunctionState.DEFINITION
|
||||
]
|
||||
await asyncio.gather(*tasks)
|
||||
else:
|
||||
|
||||
@@ -67,6 +67,7 @@ class FunctionVisitor(ast.NodeVisitor):
|
||||
def __init__(self):
|
||||
self.functions = {}
|
||||
self.imports = []
|
||||
self.pydantic_classes = []
|
||||
|
||||
def visit_Import(self, node):
|
||||
for alias in node.names:
|
||||
@@ -84,6 +85,10 @@ class FunctionVisitor(ast.NodeVisitor):
|
||||
self.imports.append(import_line)
|
||||
self.generic_visit(node)
|
||||
|
||||
# TODO(AGPT-425):
|
||||
# - Add visit_ClassDef and parse input output complex types
|
||||
# - Exclude function inside the class and 'unexpected' nested functions.
|
||||
|
||||
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
|
||||
args = []
|
||||
for arg in node.args.args:
|
||||
@@ -92,31 +97,56 @@ class FunctionVisitor(ast.NodeVisitor):
|
||||
args_str = ", ".join(args)
|
||||
return_type = ast.unparse(node.returns) if node.returns else "Unknown"
|
||||
|
||||
# Extracting the function_template with doc_string if it exists
|
||||
original_body = node.body.copy()
|
||||
# Extract doc_string & function body
|
||||
pass_block = ast.parse("pass").body[0]
|
||||
if (
|
||||
node.body
|
||||
and isinstance(node.body[0], ast.Expr)
|
||||
and isinstance(node.body[0].value, (ast.Str, ast.Constant))
|
||||
):
|
||||
node.body = node.body[:1]
|
||||
doc_string_body = [node.body[0], pass_block]
|
||||
code_body = node.body[1:]
|
||||
else:
|
||||
node.body = []
|
||||
doc_string_body = [pass_block]
|
||||
code_body = node.body
|
||||
|
||||
# add "pass" statement to the node.body
|
||||
node.body.append(ast.parse("pass").body[0])
|
||||
# Construct function template
|
||||
original_body = node.body.copy()
|
||||
node.body = doc_string_body
|
||||
function_template = ast.unparse(node)
|
||||
node.body = original_body
|
||||
|
||||
# Function is not implemented if it has pass_block as its body
|
||||
is_implemented = len(code_body) > 1 or ast.unparse(code_body[0]) != ast.unparse(
|
||||
pass_block
|
||||
)
|
||||
|
||||
self.functions[node.name] = FunctionDef(
|
||||
name=node.name,
|
||||
function_template=function_template,
|
||||
args=args_str,
|
||||
return_type=return_type,
|
||||
is_implemented=is_implemented,
|
||||
function_template=function_template,
|
||||
function_code=ast.unparse(node),
|
||||
)
|
||||
self.generic_visit(node)
|
||||
|
||||
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
||||
"""
|
||||
Visits a ClassDef node in the AST and checks if it is a Pydantic class.
|
||||
If it is a Pydantic class, adds its name to the list of Pydantic classes.
|
||||
"""
|
||||
for base in node.bases:
|
||||
base_id = getattr(base, "id", None)
|
||||
# This will only work for direct children of BaseModel
|
||||
is_pydantic = (isinstance(base, ast.Name) and base.id == "BaseModel") or (
|
||||
isinstance(base, ast.Attribute) and base.attr == "BaseModel"
|
||||
)
|
||||
if is_pydantic:
|
||||
self.pydantic_classes.append(node.name)
|
||||
|
||||
self.generic_visit(node)
|
||||
|
||||
|
||||
class DevelopAIBlock(AIBlock):
|
||||
developement_phase: DevelopmentPhase = DevelopmentPhase.DEVELOPMENT
|
||||
@@ -165,7 +195,7 @@ class DevelopAIBlock(AIBlock):
|
||||
invoke_params["function_name"]
|
||||
]
|
||||
|
||||
if "pass" in requested_func.function_code:
|
||||
if not requested_func.is_implemented:
|
||||
# Important: ValidationErrors are used in the retry prompt
|
||||
raise ValidationError(
|
||||
"Main Function body is empty, it should contain"
|
||||
@@ -211,7 +241,11 @@ class DevelopAIBlock(AIBlock):
|
||||
functionName=value.name,
|
||||
template=value.function_template,
|
||||
apiRouteSpecId=generated_response.api_route_spec.id,
|
||||
state=FunctionState.DEFINITION,
|
||||
state=FunctionState.WRITTEN
|
||||
if value.is_implemented
|
||||
else FunctionState.DEFINITION,
|
||||
rawCode=value.function_code,
|
||||
functionCode=value.function_code,
|
||||
)
|
||||
|
||||
function_defs.append(model)
|
||||
|
||||
@@ -15,6 +15,7 @@ class FunctionDef(BaseModel):
|
||||
name: str
|
||||
args: str
|
||||
return_type: str
|
||||
is_implemented: bool
|
||||
function_template: str
|
||||
function_code: str
|
||||
|
||||
|
||||
@@ -82,6 +82,8 @@ def convert_to_markdown(html: str) -> str:
|
||||
|
||||
def convert_webpages(urls: List[str], format: str) -> List[str]:
|
||||
"""
|
||||
~ THIS IS THE REQUESTED FUNCTION, SO YOU HAVE TO FULLY IMPLEMENT THIS FUNCTION ~
|
||||
|
||||
Converts a list of webpages to a specified format.
|
||||
|
||||
This function takes a list of URLs and downloads the HTML content of each webpage.
|
||||
@@ -117,13 +119,19 @@ def convert_webpages(urls: List[str], format: str) -> List[str]:
|
||||
Thinking carefully step by step. Always start your answer with your analysis of the problem and possible problems. Then discuss the types of objects that maybe useful
|
||||
|
||||
## IMPORTANT
|
||||
1. USE A SINGLE CODE BLOCK ("```python") FOR ALL PYTHON CODE (THIS IS MANDATORY)
|
||||
2. THE GENERATED CODE HAS TO BE A WORKING CODE, NO SIMPLIFICATIONS OR INCOMPLETE CODE, UNIMPLEMENTED FUNCTIONS MUST BE STUBS.
|
||||
3. CREATE STUB ONLY IF IT'S REALLY NECESSARY! TRY TO KEEP ONLY A SINGLE FUNCTION. KEEP THE CODE AS SIMPLE AS POSSIBLE WITH LESS STUBS AND ABSTRACTIONS.
|
||||
4. ONLY PROVIDE THE STUB FUNCTIONS USED IN THE IMPLEMENTED FUNCTION, NO NEED TO PROVIDE THE OTHER STUB FUNCTIONS, JUST THE REQUESTED FUNCTION AND THE STUB FUNCTIONS.
|
||||
5. USE A SINGLE REQUIREMENTS BLOCK ("```requirements") FOR ALL REQUIREMENTS CODE (THIS IS MANDATORY EVEN IF THERE ARE NO REQUIREMENTS)
|
||||
6. IF THE FUNCTION USE NON-CORE PYTHON LIBS, ADD THE IMPORTS STATEMENTS, AND ADD THE LIBS TO THE REQUIREMENTS BLOCK.
|
||||
7. YOU ARE CONTINUING AN ONGOING WORK, SO YOU ONLY NEED TO IMPLEMENT THE FUNCTIONALITY THAT IS REQUESTED, DON'T IMPLEMENT UNREQUESTED FUNCTIONALITY.
|
||||
8. DOC STRING ON EACH FUNCTION AND STUB IS MANDATORY AND AS DETAILED AS POSSIBLE! ALWAYS DEFINE: Function description, `Args`, `Returns`, and `Example`, EVEN THE STUBS. FOR STUBS, THE LONGER THE DOC STRING, THE BETTER.
|
||||
9. DO NOT CHANGE THE SIGNATURE OF THE FUNCTION, THE FUNCTION NAME, OR THE PARAMETER NAMES. THE FUNCTIONALITY MUST BE THE SAME AS THE ORIGINAL FUNCTION.
|
||||
10. AVOID NESTED FUNCTIONS, THE STUBS AND FUNCTIONS MUST BE IN THE GLOBAL SCOPE.
|
||||
* USE A SINGLE CODE BLOCK ("```python") FOR ALL PYTHON CODE, USE A SINGLE REQUIREMENTS BLOCK ("```requirements") FOR ALL REQUIREMENTS CODE (THIS IS MANDATORY)
|
||||
{% if allow_stub %}
|
||||
* THE GENERATED CODE HAS TO BE A WORKING CODE, NO SIMPLIFICATIONS OR INCOMPLETE CODE, UNIMPLEMENTED FUNCTIONS MUST BE STUBS.
|
||||
* CREATE STUB ONLY IF IT'S REALLY NECESSARY! TRY TO KEEP ONLY A SINGLE FUNCTION. KEEP THE CODE AS SIMPLE AS POSSIBLE WITH LESS STUBS AND ABSTRACTIONS.
|
||||
* ONLY PROVIDE THE STUB FUNCTIONS USED IN THE IMPLEMENTED FUNCTION, NO NEED TO PROVIDE THE OTHER STUB FUNCTIONS, JUST THE REQUESTED FUNCTION AND THE STUB FUNCTIONS.
|
||||
* IMPORTANT: ALWAYS USE `pass` KEYWORD IN THE STUBS, DO NOT RETURN DUMMY VALUES, OR USE `...` OR `None` OR RAISE EXCEPTIONS. THE STUBS MUST BE EMPTY FUNCTIONS WITH DOC STRINGS and `pass` KEYWORD.
|
||||
{% else %}
|
||||
* IMPORTANT: FOR THIS GENERATION, CREATE ONLY ONE FUNCTION WITHOUT ANY STUBS. THE GENERATED FUNCTION HAS TO BE A WORKING CODE, NO SIMPLIFICATIONS OR INCOMPLETE CODE.
|
||||
{% endif %}
|
||||
* IF THE FUNCTION USE NON-CORE PYTHON LIBS, ADD THE IMPORTS STATEMENTS, AND ADD THE LIBS TO THE REQUIREMENTS BLOCK.
|
||||
* YOU ARE CONTINUING AN ONGOING WORK, SO YOU ONLY NEED TO IMPLEMENT THE FUNCTIONALITY THAT IS REQUESTED, DON'T IMPLEMENT UNREQUESTED FUNCTIONALITY.
|
||||
* DOC STRING ON EACH FUNCTION AND STUB IS MANDATORY AND AS DETAILED AS POSSIBLE! ALWAYS DEFINE: Function description, `Args`, `Returns`, and `Example`, EVEN THE STUBS. FOR STUBS, THE LONGER THE DOC STRING, THE BETTER.
|
||||
* DO NOT CHANGE THE SIGNATURE OF THE FUNCTION, THE FUNCTION NAME, OR THE PARAMETER NAMES. THE FUNCTIONALITY MUST BE THE SAME AS THE ORIGINAL FUNCTION. IF THE REQUESTED FUNCTION IS ALREADY IMPLEMENTED, CHANGE IT ONLY IF IT'S REALLY NECESSARY.
|
||||
* AVOID NESTED FUNCTIONS, THE STUBS AND FUNCTIONS MUST BE IN THE GLOBAL SCOPE.
|
||||
* ONLY WRITE FUNCTIONS NOT CLASS, UNLESS IT'S DATA CLASS OR NAMEDTUPLE.
|
||||
* NEVER USE DUMMY DATA OR GLOBAL VARIABLES! ALWAYS PASS WHAT'S NEEDED AS ARGUMENTS! NO HARDCODED VALUES!
|
||||
@@ -1,12 +1,17 @@
|
||||
Main function name: {{ function_name }}
|
||||
Main function detail:
|
||||
{{ description }}
|
||||
Create the working code implementation of function called: {{ function_name }}
|
||||
{% if function_signature %}
|
||||
With this function signature:
|
||||
```python
|
||||
{{ function_signature }}
|
||||
```
|
||||
The created function has to match exactly as this signature!
|
||||
{% endif %}
|
||||
For additional context, this function that you need to implement will be used as part of a larger program for this goal:
|
||||
"{{ goal }}".
|
||||
|
||||
The signature has to match exactly as the one in the description.
|
||||
For additional context, this function that you need to implement will be used as part of a larger program for {{ goal }}.
|
||||
|
||||
----
|
||||
NOTE: IMPLEMENT THE REQUIRED FUNCTION WITH A REAL CODE IMPLEMENTATION, NOT JUST A STUB, PLACEHOLDER, OR PSEUDOCODE!
|
||||
{% if provided_functions %}
|
||||
----
|
||||
You can re-use these functions without introducing a new stub:
|
||||
```python
|
||||
{% for function in provided_functions %}
|
||||
@@ -17,8 +22,5 @@ You can re-use these functions without introducing a new stub:
|
||||
NOTE:
|
||||
DO NOT RE-WRITE THESE FUNCTIONS. JUST CALL IT IN THE FUNCTION THAT YOU WRITE (IF NEEDED).
|
||||
YOU SHOULD ONLY PRODUCE THE REQUIRED FUNCTION AND THE NEW STUBS (IF THERE IS ANY).
|
||||
{% endif %}
|
||||
|
||||
{% if not allow_stub %}
|
||||
IMPORTANT: FOR THIS GENERATION, CREATE ONLY ONE FUNCTION WITHOUT ANY STUBS.
|
||||
----
|
||||
{% endif %}
|
||||
@@ -0,0 +1,368 @@
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
from codex.develop.develop import FunctionVisitor
|
||||
|
||||
SAMPLE_CODE = """
|
||||
from pydantic import BaseModel
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
class Location(BaseModel):
|
||||
name: str # For named locations or coordinates as a string
|
||||
|
||||
class ProfessionalWorkingHours(BaseModel):
|
||||
professional_id: str
|
||||
start: datetime
|
||||
end: datetime
|
||||
|
||||
class Appointment(BaseModel):
|
||||
start_time: datetime
|
||||
end_time: datetime
|
||||
professional_id: str
|
||||
location: str
|
||||
|
||||
class TravelTime(BaseModel):
|
||||
start_location: str
|
||||
end_location: str
|
||||
time: timedelta
|
||||
|
||||
class SomeClass:
|
||||
start_location: str
|
||||
end_location: str
|
||||
time: timedelta
|
||||
|
||||
|
||||
def calculate_travel_time(start_location: Location, end_location: Location) -> timedelta:
|
||||
\"\"\"
|
||||
Stub function to calculate the travel time between two locations.
|
||||
|
||||
This function is intended to compute the estimated time it takes to travel from a start location to an end location.
|
||||
It can accept either named locations (e.g., "Office", "Home") or geographical coordinates in string format (e.g., "40.7128,-74.0060").
|
||||
The actual implementation of this function would involve complex logic possibly including API calls to mapping services,
|
||||
but in this stub, the specifics of how travel time is calculated are abstract.
|
||||
|
||||
Args:
|
||||
start_location (str): The starting location's name or coordinates.
|
||||
end_location (str): The ending location's name or coordinates.
|
||||
|
||||
Returns:
|
||||
timedelta: The estimated travel time between the two locations. For the purposes of this stub, a fixed
|
||||
travel time is returned to simulate functionality.
|
||||
|
||||
Example:
|
||||
calculate_travel_time("Office", "Client Site")
|
||||
> timedelta(minutes=30)
|
||||
\"\"\"
|
||||
pass
|
||||
|
||||
def is_within_working_hours(
|
||||
professional_id: str,
|
||||
proposed_time: datetime,
|
||||
working_hours: Dict[str, ProfessionalWorkingHours]
|
||||
) -> bool:
|
||||
\"\"\"
|
||||
Determination whether a proposed appointment time falls within a professional's predefined working hours.
|
||||
|
||||
This function assesses the suitability of a proposed appointment time by comparing it with the professional's working
|
||||
hours. It is particularly useful in scheduling systems where appointments need to be set during specific hours.
|
||||
|
||||
Args:
|
||||
professional_id (str): Unique identifier of the professional.
|
||||
proposed_time (datetime): The datetime object representing the proposed appointment time.
|
||||
working_hours (Dict[str, Tuple[datetime, datetime]]): A dictionary with professional_id as keys and tuples
|
||||
representing the start and end of working hours as values.
|
||||
|
||||
Returns:
|
||||
bool: A boolean value indicating if the proposed_time falls within the working hours of the specified professional.
|
||||
|
||||
Example:
|
||||
is_within_working_hours(
|
||||
"prof123",
|
||||
datetime(2023, 4, 15, 10, 0),
|
||||
{"prof123": (datetime(2023, 4, 15, 9, 0), datetime(2023, 4, 15, 17, 0))}
|
||||
)
|
||||
> True
|
||||
\"\"\"
|
||||
pass
|
||||
|
||||
def create_schedule(
|
||||
appointments: List[Appointment],
|
||||
working_hours: Dict[str, ProfessionalWorkingHours],
|
||||
travel_times: Dict[Tuple[str, str], TravelTime]
|
||||
) -> List[Appointment]:
|
||||
suggested_appointments = []
|
||||
|
||||
for prof_id, working_hour in working_hours.items():
|
||||
available_start = working_hour.start
|
||||
while available_start < working_hour.end:
|
||||
# Find end time by adding minimum appointment duration to start
|
||||
available_end = available_start + timedelta(hours=1) # Assuming 1-hour appointments
|
||||
|
||||
# Check if this slot is within working hours and not overlapping with existing appointments
|
||||
if is_within_working_hours(prof_id, available_start, working_hours) and all(
|
||||
not (appointment.start_time <= available_start < appointment.end_time or
|
||||
appointment.start_time < available_end <= appointment.end_time)
|
||||
for appointment in appointments if appointment.professional_id == prof_id
|
||||
):
|
||||
# Assuming all appointments are at the same location for simplification
|
||||
# In a real scenario, you would check travel times between locations here
|
||||
suggested_appointments.append(Appointment(
|
||||
start_time=available_start,
|
||||
end_time=available_end,
|
||||
professional_id=prof_id,
|
||||
location="Assumed Single Location" # Placeholder
|
||||
))
|
||||
# Adjust start time for next potential slot by considering travel time
|
||||
available_start = available_end + timedelta(minutes=30) # Assuming fixed travel time for simplification
|
||||
else:
|
||||
# Move to the next slot if this one is not suitable
|
||||
available_start += timedelta(minutes=15) # Check every 15 minutes for availability
|
||||
|
||||
return suggested_appointments
|
||||
"""
|
||||
|
||||
|
||||
def test_function_visitor():
|
||||
tree = ast.parse(SAMPLE_CODE)
|
||||
|
||||
visitor = FunctionVisitor()
|
||||
visitor.visit(tree)
|
||||
|
||||
# Check that all Pydantic classes are identified
|
||||
assert "SomeClass" not in visitor.pydantic_classes
|
||||
assert "ProfessionalWorkingHours" in visitor.pydantic_classes
|
||||
|
||||
# Check that all functions are identified
|
||||
assert len(visitor.pydantic_classes) == 4
|
||||
assert len(visitor.functions) == 3
|
||||
|
||||
|
||||
# Visiting a simple function definition with no arguments or return type
|
||||
def test_simple_function_definition():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a simple function definition
|
||||
code = ast.parse("def my_function():\n pass")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the function was added to the functions dictionary
|
||||
assert "my_function" in visitor.functions
|
||||
|
||||
# Assert the properties of the FunctionDef object
|
||||
function_def = visitor.functions["my_function"]
|
||||
assert function_def.name == "my_function"
|
||||
assert function_def.args == ""
|
||||
assert function_def.return_type == "Unknown"
|
||||
assert function_def.function_template == "def my_function():\n pass"
|
||||
assert function_def.function_code == "def my_function():\n pass"
|
||||
|
||||
|
||||
# Visiting a function definition with default arguments
|
||||
def test_function_with_default_arguments():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a function definition with default arguments
|
||||
code = ast.parse("def my_function(arg1, arg2='default', arg3=123):\n pass")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the function was added to the functions dictionary
|
||||
assert "my_function" in visitor.functions
|
||||
|
||||
# Assert the properties of the FunctionDef object
|
||||
function_def = visitor.functions["my_function"]
|
||||
assert function_def.name == "my_function"
|
||||
assert function_def.args == "Unknown, Unknown, Unknown"
|
||||
assert function_def.return_type == "Unknown"
|
||||
assert (
|
||||
function_def.function_template
|
||||
== "def my_function(arg1, arg2='default', arg3=123):\n pass"
|
||||
)
|
||||
assert (
|
||||
function_def.function_code
|
||||
== "def my_function(arg1, arg2='default', arg3=123):\n pass"
|
||||
)
|
||||
|
||||
|
||||
# Visiting a function definition with a decorator
|
||||
def test_visiting_function_with_decorator():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a function definition with a decorator
|
||||
code = ast.parse("@decorator\ndef my_function():\n pass")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the function was added to the functions dictionary
|
||||
assert "my_function" in visitor.functions
|
||||
|
||||
# Assert the properties of the FunctionDef object
|
||||
function_def = visitor.functions["my_function"]
|
||||
assert function_def.name == "my_function"
|
||||
assert function_def.args == ""
|
||||
assert function_def.return_type == "Unknown"
|
||||
assert function_def.function_template == "@decorator\ndef my_function():\n pass"
|
||||
assert function_def.function_code == "@decorator\ndef my_function():\n pass"
|
||||
|
||||
|
||||
# Visiting a class definition with no Pydantic inheritance
|
||||
def test_visiting_class_definition_no_pydantic_inheritance():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a class definition with no Pydantic inheritance
|
||||
code = ast.parse("class MyClass:\n pass")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the pydantic_classes list is empty
|
||||
assert len(visitor.pydantic_classes) == 0
|
||||
|
||||
|
||||
# Visiting a class definition with Pydantic inheritance
|
||||
def test_visiting_class_with_pydantic_inheritance():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a class definition with Pydantic inheritance
|
||||
code = ast.parse("class MyClass(pydantic.BaseModel):\n pass")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the class name was added to the list of Pydantic classes
|
||||
assert "MyClass" in visitor.pydantic_classes
|
||||
|
||||
|
||||
# Visiting an import statement with an alias
|
||||
def test_visiting_import_statement_with_alias():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for an import statement with an alias
|
||||
code = ast.parse("import module as m")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the import statement was added to the imports list
|
||||
assert "import module as m" in visitor.imports
|
||||
|
||||
|
||||
# Visiting an import statement with no alias
|
||||
def test_visiting_import_statement_with_no_alias():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for an import statement with no alias
|
||||
code = ast.parse("import module")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit_Import(code.body[0])
|
||||
|
||||
# Assert that the import line was added to the imports list
|
||||
assert visitor.imports == ["import module"]
|
||||
|
||||
|
||||
# Visiting a function definition with annotations that are not strings or constants
|
||||
def test_visiting_function_with_non_string_annotations():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a function definition with non-string annotations
|
||||
code = ast.parse(
|
||||
"def my_function(arg1: int, arg2: List[str]) -> Dict[str, int]:\n pass"
|
||||
)
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the function was added to the functions dictionary
|
||||
assert "my_function" in visitor.functions
|
||||
|
||||
# Assert the properties of the FunctionDef object
|
||||
function_def = visitor.functions["my_function"]
|
||||
assert function_def.name == "my_function"
|
||||
assert function_def.args == "int, List[str]"
|
||||
assert function_def.return_type == "Dict[str, int]"
|
||||
assert (
|
||||
function_def.function_template
|
||||
== "def my_function(arg1: int, arg2: List[str]) -> Dict[str, int]:\n pass"
|
||||
)
|
||||
assert (
|
||||
function_def.function_code
|
||||
== "def my_function(arg1: int, arg2: List[str]) -> Dict[str, int]:\n pass"
|
||||
)
|
||||
|
||||
|
||||
# Visiting a function definition with a return annotation that is not a string or constant
|
||||
def test_visiting_function_with_non_string_return_annotation():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a function definition with a non-string return annotation
|
||||
code = ast.parse("def my_function() -> int:\n pass")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the function was added to the functions dictionary
|
||||
assert "my_function" in visitor.functions
|
||||
|
||||
# Assert the properties of the FunctionDef object
|
||||
function_def = visitor.functions["my_function"]
|
||||
assert function_def.name == "my_function"
|
||||
assert function_def.args == ""
|
||||
assert function_def.return_type == "int"
|
||||
assert function_def.function_template == "def my_function() -> int:\n pass"
|
||||
assert function_def.function_code == "def my_function() -> int:\n pass"
|
||||
|
||||
|
||||
# Visiting a class definition with a body that is not a list of statements
|
||||
def test_visiting_class_definition_with_non_list_body():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a class definition with a non-list body
|
||||
code = ast.parse("class MyClass:\n x = 1")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the class was not added to the pydantic_classes list
|
||||
assert "MyClass" not in visitor.pydantic_classes
|
||||
|
||||
|
||||
# Visiting a function definition with a body that is not a list of statements
|
||||
def test_visiting_function_with_non_list_body():
|
||||
# Initialize FunctionVisitor
|
||||
visitor = FunctionVisitor()
|
||||
|
||||
# Create AST for a function definition with a non-list body
|
||||
code = ast.parse("def my_function():\n print('Hello, World!')")
|
||||
|
||||
# Visit the AST
|
||||
visitor.visit(code)
|
||||
|
||||
# Assert that the function was added to the functions dictionary
|
||||
assert "my_function" in visitor.functions
|
||||
|
||||
# Assert the properties of the FunctionDef object
|
||||
function_def = visitor.functions["my_function"]
|
||||
assert function_def.name == "my_function"
|
||||
assert function_def.args == ""
|
||||
assert function_def.return_type == "Unknown"
|
||||
assert function_def.function_template == "def my_function():\n pass"
|
||||
assert (
|
||||
function_def.function_code == "def my_function():\n print('Hello, World!')"
|
||||
)
|
||||
@@ -127,8 +127,8 @@ async def test_recursive_create_code_graphs():
|
||||
setup_logging(local=True)
|
||||
|
||||
ids = Identifiers(
|
||||
user_id="123e4567-e89b-12d3-a456-426614174000",
|
||||
app_id="d3954dee-6b41-47f5-be2f-a253f7544a59",
|
||||
user_id=user_id_1,
|
||||
app_id=app_id_1,
|
||||
)
|
||||
spec = await get_latest_specification(ids.user_id, ids.app_id)
|
||||
ans = await agent.develop_application(ids=ids, spec=spec)
|
||||
|
||||
Reference in new issue
Block a user