Refactor out aiservice manage.py and associated settings to the correct top-level dir so tests can run. Fix ellipsis in AST; allow ellipsis if they are in type annotations.

This commit is contained in:
afik.cohen 2024-05-31 16:51:43 -07:00
parent 2c2454f88a
commit 1ff663ec51
14 changed files with 103 additions and 14 deletions

View file

@ -0,0 +1,35 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Django Tests: testgen.tests" type="DjangoTestsConfigurationType">
<module name="codeflash" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="DJANGO_SETTINGS_MODULE" value="settings" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<EXTENSION ID="net.ashald.envfile">
<option name="IS_ENABLED" value="true" />
<option name="IS_SUBST" value="false" />
<option name="IS_PATH_MACRO_SUPPORTED" value="false" />
<option name="IS_IGNORE_MISSING_FILES" value="false" />
<option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
<ENTRIES>
<ENTRY IS_ENABLED="true" PARSER="runconfig" IS_EXECUTABLE="false" />
<ENTRY IS_ENABLED="true" PARSER="env" IS_EXECUTABLE="false" PATH="django/aiservice/.env" />
</ENTRIES>
</EXTENSION>
<option name="TARGET" value="testgen.tests" />
<option name="SETTINGS_FILE" value="" />
<option name="CUSTOM_SETTINGS" value="false" />
<option name="USE_OPTIONS" value="false" />
<option name="OPTIONS" value="" />
<method v="2" />
</configuration>
</component>

View file

@ -6,7 +6,7 @@
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="DJANGO_SETTINGS_MODULE" value="aiservice.settings" />
<env name="DJANGO_SETTINGS_MODULE" value="settings" />
</envs>
<option name="SDK_HOME" value="$USER_HOME$/mambaforge/envs/aiservice/bin/python" />
<option name="SDK_NAME" value="$USER_HOME$/miniforge3/envs/aiservice" />

View file

@ -0,0 +1 @@
# required for the django test collector to find tests in tests/

View file

@ -10,6 +10,6 @@ import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "aiservice.settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
application = get_asgi_application()

View file

@ -10,6 +10,6 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "aiservice.settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
application = get_wsgi_application()

View file

@ -1,5 +1,6 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import platform
import sys
@ -10,7 +11,7 @@ from aiservice.env_specific import load_env, set_logging_level
def main():
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "aiservice.settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
# Get the network name of the machine
machine_id = platform.node()
try:

View file

@ -18,8 +18,6 @@ import dj_database_url
import dotenv
import sentry_sdk
from aiservice import apps
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR: Path = Path(__file__).resolve().parent.parent
@ -57,7 +55,7 @@ INSTALLED_APPS: list[str] = [
"django.contrib.contenttypes",
"django.contrib.staticfiles",
"log_features.apps.LoggingConfig",
"apps.AiServiceConfig", # Add the app containing the management commands
"aiservice.apps.AiServiceConfig", # Add the app containing the management commands
]
MIDDLEWARE: list[str] = [
@ -66,7 +64,7 @@ MIDDLEWARE: list[str] = [
"aiservice.middleware.healthcheck.HealthCheckMiddleware",
]
ROOT_URLCONF: str = "aiservice.urls"
ROOT_URLCONF: str = "urls"
TEMPLATES: list[str] = []

View file

@ -8,21 +8,21 @@ from pathlib import Path
from typing import SupportsIndex
import isort
from aiservice.common_utils import parse_python_version
from aiservice.env_specific import create_openai_client, debug_log_sensitive_data
from aiservice.models.aimodels import EXECUTE_MODEL, EXPLAIN_MODEL, LLM, PLAN_MODEL
from aiservice.models.functions_to_optimize import FunctionToOptimize
from authapp.auth import AuthBearer
from log_features.log_features import log_features
from ninja import NinjaAPI, Schema
from pydantic import model_validator
from testgen.instrumentation.edit_generated_test import (
parse_module_to_cst,
replace_definition_with_import,
)
from testgen.instrumentation.instrument_test_source import instrument_test_source
from aiservice.common_utils import parse_python_version
from aiservice.env_specific import create_openai_client, debug_log_sensitive_data
from aiservice.models.aimodels import EXECUTE_MODEL, EXPLAIN_MODEL, LLM, PLAN_MODEL
from aiservice.models.functions_to_optimize import FunctionToOptimize
testgen_api = NinjaAPI(auth=AuthBearer(), urls_namespace="testgen")
openai_client = create_openai_client()
@ -48,7 +48,18 @@ color_prefix_by_role = {
def ellipsis_in_ast(module: ast.AST) -> bool:
return any(isinstance(node, ast.Constant) and node.value == ... for node in ast.walk(module))
# Add parent attribute to nodes for easier traversal
for node in ast.walk(module):
for child in ast.iter_child_nodes(node):
child.parent = node
for node in ast.walk(module):
if isinstance(node, ast.Constant) and node.value is Ellipsis:
# Check if the ellipsis is part of a type annotation
if isinstance(node.parent, (ast.Subscript, ast.Index, ast.Tuple)):
continue
return True
return False
def print_messages(

View file

@ -0,0 +1,43 @@
import ast
from testgen.testgen import ellipsis_in_ast
from django.test import TestCase
class TestEllipsisInAst(TestCase):
def test_ellipsis_in_ast_with_ellipsis(self) -> None:
"""Test that ellipsis_in_ast detects an ellipsis in the function body."""
code = """
def example_function():
return ...
"""
module = ast.parse(code)
assert ellipsis_in_ast(module) is True
def test_ellipsis_in_ast_without_ellipsis(self) -> None:
"""Test that ellipsis_in_ast does not detect an ellipsis when there is none."""
code = """
def example_function():
return 42
"""
module = ast.parse(code)
assert ellipsis_in_ast(module) is False
def test_ellipsis_in_ast_in_type_annotation(self) -> None:
"""Test that ellipsis_in_ast ignores ellipses in type annotations."""
code = """
def example_function(param: tuple[int, ...]) -> None:
pass
"""
module = ast.parse(code)
assert ellipsis_in_ast(module) is False
def test_ellipsis_in_ast_in_type_annotation_union(self) -> None:
"""Test that ellipsis_in_ast ignores ellipses in type annotations with unions."""
code = """
def example_function(param: tuple[int, ...] | list[int]) -> None:
pass
"""
module = ast.parse(code)
assert ellipsis_in_ast(module) is False