diff --git a/.idea/runConfigurations/Django_Tests__testgen_tests.xml b/.idea/runConfigurations/Django_Tests__testgen_tests.xml
new file mode 100644
index 000000000..f7be99716
--- /dev/null
+++ b/.idea/runConfigurations/Django_Tests__testgen_tests.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/aiservice.xml b/.idea/runConfigurations/aiservice.xml
index a97aaa082..fd366f40e 100644
--- a/.idea/runConfigurations/aiservice.xml
+++ b/.idea/runConfigurations/aiservice.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/django/aiservice/__init__.py b/django/aiservice/__init__.py
new file mode 100644
index 000000000..9db25d434
--- /dev/null
+++ b/django/aiservice/__init__.py
@@ -0,0 +1 @@
+# required for the django test collector to find tests in tests/
diff --git a/django/aiservice/aiservice/asgi.py b/django/aiservice/aiservice/asgi.py
index e7fc7bd55..354b6c3d6 100644
--- a/django/aiservice/aiservice/asgi.py
+++ b/django/aiservice/aiservice/asgi.py
@@ -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()
diff --git a/django/aiservice/aiservice/wsgi.py b/django/aiservice/aiservice/wsgi.py
index bde021e51..d95a16545 100644
--- a/django/aiservice/aiservice/wsgi.py
+++ b/django/aiservice/aiservice/wsgi.py
@@ -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()
diff --git a/django/aiservice/aiservice/gunicorn.conf.py b/django/aiservice/gunicorn.conf.py
similarity index 100%
rename from django/aiservice/aiservice/gunicorn.conf.py
rename to django/aiservice/gunicorn.conf.py
diff --git a/django/aiservice/aiservice/manage.py b/django/aiservice/manage.py
similarity index 92%
rename from django/aiservice/aiservice/manage.py
rename to django/aiservice/manage.py
index ef5e295b1..3a2210e34 100755
--- a/django/aiservice/aiservice/manage.py
+++ b/django/aiservice/manage.py
@@ -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:
diff --git a/django/aiservice/aiservice/settings.py b/django/aiservice/settings.py
similarity index 96%
rename from django/aiservice/aiservice/settings.py
rename to django/aiservice/settings.py
index 36b6e89b3..f435c5ddc 100644
--- a/django/aiservice/aiservice/settings.py
+++ b/django/aiservice/settings.py
@@ -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] = []
diff --git a/django/aiservice/aiservice/start_gunicorn.sh b/django/aiservice/start_gunicorn.sh
similarity index 100%
rename from django/aiservice/aiservice/start_gunicorn.sh
rename to django/aiservice/start_gunicorn.sh
diff --git a/django/aiservice/testgen/testgen.py b/django/aiservice/testgen/testgen.py
index 5b2fd657b..cf811e2de 100644
--- a/django/aiservice/testgen/testgen.py
+++ b/django/aiservice/testgen/testgen.py
@@ -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(
diff --git a/django/aiservice/testgen/tests/__init__.py b/django/aiservice/testgen/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/django/aiservice/testgen/tests/test_ellipsis_in_ast.py b/django/aiservice/testgen/tests/test_ellipsis_in_ast.py
new file mode 100644
index 000000000..944891ebf
--- /dev/null
+++ b/django/aiservice/testgen/tests/test_ellipsis_in_ast.py
@@ -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
diff --git a/django/aiservice/aiservice/urls.py b/django/aiservice/urls.py
similarity index 100%
rename from django/aiservice/aiservice/urls.py
rename to django/aiservice/urls.py
diff --git a/django/aiservice/aiservice/uvicorn_worker.py b/django/aiservice/uvicorn_worker.py
similarity index 100%
rename from django/aiservice/aiservice/uvicorn_worker.py
rename to django/aiservice/uvicorn_worker.py