diff --git a/apps/evaluations/evaluators.py b/apps/evaluations/evaluators.py index 1dbe8193c2..a6d47e1332 100644 --- a/apps/evaluations/evaluators.py +++ b/apps/evaluations/evaluators.py @@ -13,7 +13,7 @@ from apps.service_providers.llm_service.main import LlmService from apps.service_providers.llm_service.prompt_context import SafeAccessWrapper from apps.service_providers.llm_service.retry import RATE_LIMIT_EXCEPTIONS -from apps.service_providers.models import LlmProviderModel +from apps.service_providers.models import LlmProvider, LlmProviderModel from apps.utils.python_execution import RestrictedPythonExecutionMixin, get_code_error_message @@ -41,7 +41,6 @@ class LLMResponseMixin(BaseModel): ) def get_llm_service(self) -> LlmService: - from apps.service_providers.models import LlmProvider # noqa: PLC0415 try: provider = LlmProvider.objects.get(id=self.llm_provider_id) diff --git a/apps/evaluations/models.py b/apps/evaluations/models.py index a2f5878e94..b333293be1 100644 --- a/apps/evaluations/models.py +++ b/apps/evaluations/models.py @@ -14,6 +14,7 @@ from apps.chat.models import ChatMessage, ChatMessageType from apps.evaluations.utils import make_evaluation_messages_from_sessions +from apps.experiments.filters import ChatMessageFilter from apps.experiments.models import ExperimentSession from apps.teams.models import BaseTeamModel, Team from apps.teams.utils import get_slug_for_team @@ -115,7 +116,6 @@ def __str__(self): def create_from_sessions( cls, team: Team, external_session_ids, filtered_session_ids=None, filter_params=None, timezone=None ) -> list[EvaluationMessage]: - from apps.experiments.filters import ChatMessageFilter # noqa: PLC0415 base_queryset = ( ChatMessage.objects.filter( @@ -295,7 +295,9 @@ def run(self, run_type=EvaluationRunType.FULL) -> EvaluationRun: type=run_type, ) - from apps.evaluations.tasks import run_evaluation_task # noqa: PLC0415 + from apps.evaluations.tasks import ( + run_evaluation_task, # noqa: PLC0415 - circular: evaluations.tasks imports evaluations.models + ) run_evaluation_task.delay(run.id) return run diff --git a/apps/evaluations/tables.py b/apps/evaluations/tables.py index c7698e9f10..c4da8b15d5 100644 --- a/apps/evaluations/tables.py +++ b/apps/evaluations/tables.py @@ -56,8 +56,6 @@ class EvaluationConfigTable(tables.Table): def render_evaluators(self, value, record): """Render the evaluators column with icons and labels in an unordered list.""" - from apps.evaluations.utils import get_evaluator_type_display # noqa: PLC0415 - if not value.exists(): return "—" diff --git a/apps/evaluations/tasks.py b/apps/evaluations/tasks.py index 77ff3de9c8..867b68e0e2 100644 --- a/apps/evaluations/tasks.py +++ b/apps/evaluations/tasks.py @@ -10,12 +10,14 @@ from celery import chord, shared_task from celery.utils.log import get_task_logger from celery_progress.backend import ProgressRecorder +from django.http import QueryDict from django.utils import timezone from taskbadger.celery import Task as TaskbadgerTask from apps.channels.models import ChannelPlatform, ExperimentChannel from apps.channels.tasks import handle_evaluation_message from apps.chat.models import Chat, ChatMessage, ChatMessageType +from apps.evaluations.aggregation import compute_aggregates_for_run from apps.evaluations.const import PREVIEW_SAMPLE_SIZE from apps.evaluations.exceptions import HistoryParseException from apps.evaluations.models import ( @@ -33,6 +35,7 @@ from apps.experiments.models import Experiment, ExperimentSession, Participant from apps.files.models import File from apps.teams.utils import current_team +from apps.web.dynamic_filters.datastructures import FilterParams EVAL_SESSIONS_TTL_DAYS = 30 @@ -175,7 +178,6 @@ def mark_evaluation_complete(results, evaluation_run_id): results: List of results from the group tasks (unused but required by chord) evaluation_run_id: ID of the evaluation run to mark complete """ - from apps.evaluations.aggregation import compute_aggregates_for_run # noqa: PLC0415 try: evaluation_run = EvaluationRun.objects.get(id=evaluation_run_id) @@ -658,7 +660,6 @@ def upload_evaluation_run_results_task(self, evaluation_run_id, csv_data, team_i def _upload_evaluation_run_results(progress_recorder, evaluation_run_id, csv_data, team_id, column_mappings=None): - from apps.evaluations.aggregation import compute_aggregates_for_run # noqa: PLC0415 if not csv_data: return {"success": False, "error": "CSV file is empty"} @@ -802,9 +803,6 @@ def create_dataset_from_sessions_task( filter_query: Serialized filter parameters as query string (or None) timezone: Timezone for filtering """ - from django.http import QueryDict # noqa: PLC0415 - - from apps.web.dynamic_filters.datastructures import FilterParams # noqa: PLC0415 progress_recorder = ProgressRecorder(self) dataset = None diff --git a/apps/evaluations/tests/test_dataset_csv_download.py b/apps/evaluations/tests/test_dataset_csv_download.py index dc791ef189..36b8cd8a7e 100644 --- a/apps/evaluations/tests/test_dataset_csv_download.py +++ b/apps/evaluations/tests/test_dataset_csv_download.py @@ -1,5 +1,6 @@ import csv import io +import json import pytest from django.urls import reverse @@ -240,7 +241,6 @@ def test_download_dataset_csv_with_participant_data_and_session_state(client, te assert row5["id"] == str(message5.id) assert row5["input_content"] == "Complex data" # Nested structures should be serialized as JSON strings - import json # noqa: PLC0415 assert json.loads(row5["context.nested"]) == {"foo": {"bar": [1, 2, "3"]}} assert json.loads(row5["participant_data.preferences"]) == { diff --git a/apps/evaluations/tests/test_evaluation_run_csv_upload.py b/apps/evaluations/tests/test_evaluation_run_csv_upload.py index 7a58237aee..18b8326566 100644 --- a/apps/evaluations/tests/test_evaluation_run_csv_upload.py +++ b/apps/evaluations/tests/test_evaluation_run_csv_upload.py @@ -2,6 +2,8 @@ import pytest +from apps.evaluations.aggregation import compute_aggregates_for_run +from apps.evaluations.models import EvaluationRunAggregate from apps.evaluations.tasks import _upload_evaluation_run_results, process_evaluation_results_csv_rows from apps.evaluations.views.evaluation_config_views import generate_evaluation_results_column_suggestions from apps.utils.factories.evaluations import ( @@ -237,8 +239,6 @@ def test_process_csv_no_update_when_value_unchanged(evaluation_setup): @pytest.mark.django_db() def test_upload_task_recomputes_aggregates(evaluation_setup): """Test that uploading CSV results triggers aggregate recalculation""" - from apps.evaluations.aggregation import compute_aggregates_for_run # noqa: PLC0415 - from apps.evaluations.models import EvaluationRunAggregate # noqa: PLC0415 # Compute initial aggregates compute_aggregates_for_run(evaluation_setup["run"]) diff --git a/apps/evaluations/utils.py b/apps/evaluations/utils.py index 105de36201..71fb99ffd0 100644 --- a/apps/evaluations/utils.py +++ b/apps/evaluations/utils.py @@ -50,7 +50,7 @@ def get_evaluator_type_info() -> dict[str, dict[str, str | None]]: Returns: Dict mapping evaluator class names to their schema info (label, icon) """ - from apps.evaluations import evaluators # noqa: PLC0415 + from apps.evaluations import evaluators # noqa: PLC0415 - circular: evaluators imports evaluations.utils evaluator_classes = [ cls @@ -80,7 +80,9 @@ def get_evaluators_with_schema(team) -> list[dict]: Returns: List of dicts containing evaluator info with schema data """ - from apps.evaluations.models import Evaluator # noqa: PLC0415 + from apps.evaluations.models import ( + Evaluator, # noqa: PLC0415 - circular: evaluations.models imports evaluations.utils + ) evaluator_type_info = get_evaluator_type_info() @@ -212,7 +214,10 @@ def _clean_field_name(field_name): def make_evaluation_messages_from_sessions(message_ids_per_session: dict[str, list[str]]) -> list["EvaluationMessage"]: - from apps.evaluations.models import EvaluationMessage, EvaluationMessageContent # noqa: PLC0415 + from apps.evaluations.models import ( # noqa: PLC0415 - circular: evaluations.models imports evaluations.utils + EvaluationMessage, + EvaluationMessageContent, + ) def _add_additional_context(msg, existing_context): if comments := list(msg.comments.all()): diff --git a/apps/evaluations/views/evaluation_config_views.py b/apps/evaluations/views/evaluation_config_views.py index 2fc88c5578..a91a016f85 100644 --- a/apps/evaluations/views/evaluation_config_views.py +++ b/apps/evaluations/views/evaluation_config_views.py @@ -5,6 +5,7 @@ from functools import cached_property from io import StringIO +from django.conf import settings from django.contrib.auth.decorators import permission_required from django.contrib.auth.mixins import PermissionRequiredMixin from django.http import HttpResponse, HttpResponseRedirect, JsonResponse @@ -293,7 +294,6 @@ def get_table_class(self): Inspect the first row's keys and build a Table subclass with one Column per field. """ - from django.conf import settings # noqa: PLC0415 data = self.get_table_data() if not data: diff --git a/apps/evaluations/views/evaluator_views.py b/apps/evaluations/views/evaluator_views.py index c117b1b036..e6ed6d4506 100644 --- a/apps/evaluations/views/evaluator_views.py +++ b/apps/evaluations/views/evaluator_views.py @@ -6,6 +6,8 @@ from django.views.generic import CreateView, DeleteView, TemplateView, UpdateView from django_tables2 import SingleTableView +from apps.custom_actions.schema_utils import resolve_references +from apps.evaluations import evaluators from apps.evaluations.forms import EvaluatorForm from apps.evaluations.models import Evaluator from apps.evaluations.tables import EvaluatorTable @@ -130,8 +132,6 @@ def delete(self, request, *args, **kwargs): def _evaluator_schemas(): """Returns schemas for all available evaluator classes.""" - from apps.evaluations import evaluators # noqa: PLC0415 - schemas = [] evaluator_classes = [ @@ -148,8 +148,6 @@ def _evaluator_schemas(): def _get_evaluator_schema(evaluator_class): """Get schema for a single evaluator class.""" - from apps.custom_actions.schema_utils import resolve_references # noqa: PLC0415 - schema = resolve_references(evaluator_class.model_json_schema()) schema.pop("$defs", None) diff --git a/apps/experiments/management/commands/fix_vector_store_duplication.py b/apps/experiments/management/commands/fix_vector_store_duplication.py index 1ac95c70b2..84fb6fd458 100644 --- a/apps/experiments/management/commands/fix_vector_store_duplication.py +++ b/apps/experiments/management/commands/fix_vector_store_duplication.py @@ -5,6 +5,7 @@ from apps.assistants.models import OpenAiAssistant from apps.assistants.sync import push_assistant_to_openai +from apps.teams.models import Team from apps.teams.utils import current_team @@ -14,7 +15,6 @@ def add_arguments(self, parser): parser.add_argument("--assistant", help="A specific assistant id", required=False) def handle(self, team, assistant, **options): - from apps.teams.models import Team # noqa: PLC0415 assistants = [] if assistant: diff --git a/apps/experiments/models.py b/apps/experiments/models.py index af0152346c..4588aeda02 100644 --- a/apps/experiments/models.py +++ b/apps/experiments/models.py @@ -36,6 +36,7 @@ from field_audit import audit_fields from field_audit.models import AuditAction, AuditingManager +from apps.annotations.models import CustomTaggedItem from apps.chat.models import Chat, ChatMessage, ChatMessageType from apps.experiments import model_audit_fields from apps.experiments.versioning import VersionDetails, VersionField, VersionsMixin, VersionsObjectManagerMixin, differs @@ -933,7 +934,9 @@ def archive(self): self.pipeline.archive() def delete_experiment_channels(self): - from apps.channels.models import ExperimentChannel # noqa: PLC0415 + from apps.channels.models import ( + ExperimentChannel, # noqa: PLC0415 - circular: channels.models imports experiments.models + ) for channel in ExperimentChannel.objects.filter(experiment_id=self.id): channel.soft_delete() @@ -1071,9 +1074,13 @@ def get_assistant(self): - If no assistant node is found or if the pipeline is not set, it returns the default assistant associated with the instance. """ - from apps.assistants.models import OpenAiAssistant # noqa: PLC0415 - from apps.pipelines.models import Node # noqa: PLC0415 - from apps.pipelines.nodes.nodes import AssistantNode # noqa: PLC0415 + from apps.assistants.models import ( + OpenAiAssistant, # noqa: PLC0415 - circular: assistants.models imports experiments.models + ) + from apps.pipelines.models import Node # noqa: PLC0415 - circular: pipelines.models imports experiments.models + from apps.pipelines.nodes.nodes import ( + AssistantNode, # noqa: PLC0415 - circular: pipelines.nodes imports experiments.models + ) if self.pipeline: node_name = AssistantNode.__name__ @@ -1146,7 +1153,9 @@ def __str__(self): return self.identifier def get_platform_display(self): - from apps.channels.models import ChannelPlatform # noqa: PLC0415 + from apps.channels.models import ( + ChannelPlatform, # noqa: PLC0415 - circular: channels.models imports experiments.models + ) try: return ChannelPlatform(self.platform).label @@ -1220,7 +1229,9 @@ def get_schedules_for_experiment( as_dict: If True, the data will be returned as an array of dictionaries, otherwise an an array of strings timezone: The timezone to use for the dates. Defaults to the active timezone. """ - from apps.events.models import ScheduledMessage # noqa: PLC0415 + from apps.events.models import ( + ScheduledMessage, # noqa: PLC0415 - circular: events.models imports experiments.models + ) messages = ( ScheduledMessage.objects.filter( @@ -1351,8 +1362,6 @@ def get_queryset(self): return ExperimentSessionQuerySet(self.model, using=self._db) def get_table_queryset(self, team, experiment_id=None): - from apps.annotations.models import CustomTaggedItem # noqa: PLC0415 - queryset = self.get_queryset().filter(team=team) if experiment_id: queryset = queryset.filter(experiment__id=experiment_id) @@ -1462,7 +1471,9 @@ def is_stale(self) -> bool: """A Channel Session is considered stale if the experiment that the channel points to differs from the one that the experiment session points to. This will happen when the user repurposes the channel to point to another experiment.""" - from apps.channels.models import ChannelPlatform # noqa: PLC0415 + from apps.channels.models import ( + ChannelPlatform, # noqa: PLC0415 - circular: channels.models imports experiments.models + ) if self.experiment_channel.platform in ChannelPlatform.team_global_platforms(): return False @@ -1496,8 +1507,12 @@ def end(self, commit: bool = True, trigger_type=None): Raises: ValueError: If trigger_type is specified but commit is not. """ - from apps.events.models import StaticTriggerType # noqa: PLC0415 - from apps.events.tasks import enqueue_static_triggers # noqa: PLC0415 + from apps.events.models import ( + StaticTriggerType, # noqa: PLC0415 - circular: events.models imports experiments.models + ) + from apps.events.tasks import ( + enqueue_static_triggers, # noqa: PLC0415 - circular: events.tasks imports experiments.models + ) if trigger_type and not commit: raise ValueError("Commit must be True when trigger_type is specified") @@ -1574,8 +1589,10 @@ def _bot_prompt_for_user( """Sends the `instruction_prompt` along with the chat history to the LLM to formulate an appropriate prompt message. The response from the bot will be saved to the chat history. """ - from apps.chat.bots import EventBot # noqa: PLC0415 - from apps.service_providers.llm_service.history_managers import ExperimentHistoryManager # noqa: PLC0415 + from apps.chat.bots import EventBot # noqa: PLC0415 - circular: chat.bots imports experiments.models + from apps.service_providers.llm_service.history_managers import ( + ExperimentHistoryManager, # noqa: PLC0415 - circular: history_managers imports experiments.models + ) experiment = use_experiment or self.experiment history_manager = ExperimentHistoryManager(session=self, experiment=experiment, trace_service=trace_service) @@ -1586,7 +1603,7 @@ def try_send_message(self, message: str): """Tries to send a message to this user session as the bot. Note that `message` will be send to the user directly. This is not an instruction to the bot. """ - from apps.chat.channels import ChannelBase # noqa: PLC0415 + from apps.chat.channels import ChannelBase # noqa: PLC0415 - circular: chat.channels imports experiments.models channel = ChannelBase.from_experiment_session(self) channel.send_message_to_user(message) @@ -1617,8 +1634,14 @@ def get_experiment_version_number(self) -> int: def requires_participant_data(self) -> bool: """Determines if participant data is required for this session""" - from apps.assistants.models import OpenAiAssistant # noqa: PLC0415 - from apps.pipelines.nodes.nodes import AssistantNode, LLMResponseWithPrompt, RouterNode # noqa: PLC0415 + from apps.assistants.models import ( + OpenAiAssistant, # noqa: PLC0415 - circular: assistants.models imports experiments.models + ) + from apps.pipelines.nodes.nodes import ( # noqa: PLC0415 - circular: pipelines.nodes imports experiments.models + AssistantNode, + LLMResponseWithPrompt, + RouterNode, + ) if self.experiment.pipeline: assistant_ids = self.experiment.pipeline.get_node_param_values(AssistantNode, param_name="assistant_id") diff --git a/apps/experiments/tasks.py b/apps/experiments/tasks.py index 6402c22899..0c59effc04 100644 --- a/apps/experiments/tasks.py +++ b/apps/experiments/tasks.py @@ -164,8 +164,10 @@ def get_prompt_builder_response_task(team_id: int, user_id, data_dict: dict) -> def _convert_prompt_builder_history(messages_history): - # lazy import to avoid import on startup - from langchain_core.messages import AIMessage, HumanMessage # noqa: PLC0415 + from langchain_core.messages import ( # noqa: PLC0415 - lazy: avoid langchain import on startup + AIMessage, + HumanMessage, + ) history = [] for message in messages_history: diff --git a/apps/experiments/views/experiment.py b/apps/experiments/views/experiment.py index 17d59d8846..1c95ce164f 100644 --- a/apps/experiments/views/experiment.py +++ b/apps/experiments/views/experiment.py @@ -2,7 +2,7 @@ import uuid from datetime import datetime, timedelta from typing import cast -from urllib.parse import urlparse +from urllib.parse import urlencode, urlparse import jwt from celery.result import AsyncResult @@ -42,6 +42,7 @@ from field_audit.models import AuditAction from apps.analysis.const import LANGUAGE_CHOICES +from apps.analysis.translation import translate_messages_with_llm from apps.annotations.models import CustomTaggedItem, Tag from apps.channels.datamodels import Attachment, AttachmentType from apps.channels.models import ChannelPlatform @@ -690,7 +691,6 @@ def experiment_session_messages_view(request, team_slug: str, experiment_id: uui @experiment_session_view() @verify_session_access_cookie def translate_messages_view(request, team_slug: str, experiment_id: uuid.UUID, session_id: str): - from apps.analysis.translation import translate_messages_with_llm # noqa: PLC0415 session = request.experiment_session provider_id = request.POST.get("llm_provider", "") @@ -752,8 +752,6 @@ def redirect_to_messages_view(request, session): params["show_original_translation"] = show_original_translation if params: - from urllib.parse import urlencode # noqa: PLC0415 - url += "?" + urlencode(params) return HttpResponseRedirect(url) diff --git a/apps/human_annotations/models.py b/apps/human_annotations/models.py index 284153bf25..56b075e958 100644 --- a/apps/human_annotations/models.py +++ b/apps/human_annotations/models.py @@ -237,7 +237,9 @@ def _update_item_review_count(self): item.update_status(save=False) item.save(update_fields=["review_count", "status"]) - from apps.human_annotations.aggregation import compute_aggregates_for_queue # noqa: PLC0415 + from apps.human_annotations.aggregation import ( + compute_aggregates_for_queue, # noqa: PLC0415 - circular: aggregation imports human_annotations.models + ) try: compute_aggregates_for_queue(item.queue) diff --git a/apps/human_annotations/tests/test_views.py b/apps/human_annotations/tests/test_views.py index e0e6efe4c2..34d961297c 100644 --- a/apps/human_annotations/tests/test_views.py +++ b/apps/human_annotations/tests/test_views.py @@ -14,9 +14,10 @@ AnnotationQueue, AnnotationStatus, ) +from apps.human_annotations.tables import AnnotationSessionsSelectionTable from apps.teams.backends import ANNOTATION_REVIEWER_GROUP from apps.teams.models import Flag -from apps.utils.factories.experiment import ExperimentSessionFactory +from apps.utils.factories.experiment import ChatMessageFactory, ExperimentSessionFactory from apps.utils.factories.human_annotations import ( AnnotationItemFactory, AnnotationQueueFactory, @@ -739,9 +740,6 @@ def test_add_session_to_queue_post_duplicate_returns_200( @pytest.mark.django_db() def test_annotation_sessions_selection_table_has_selection_column(team_with_users): - from apps.human_annotations.tables import AnnotationSessionsSelectionTable # noqa: PLC0415 - from apps.utils.factories.experiment import ExperimentSessionFactory # noqa: PLC0415 - session = ExperimentSessionFactory.create(team=team_with_users) table = AnnotationSessionsSelectionTable([session]) assert "selection" in table.columns @@ -755,8 +753,6 @@ def test_annotation_sessions_selection_table_has_selection_column(team_with_user @pytest.mark.django_db() def test_queue_sessions_table_view(client, team_with_users, queue): - from apps.utils.factories.experiment import ExperimentSessionFactory # noqa: PLC0415 - ExperimentSessionFactory.create_batch(3, team=team_with_users) url = reverse("human_annotations:queue_sessions_table", args=[team_with_users.slug, queue.pk]) response = client.get(url) @@ -765,8 +761,6 @@ def test_queue_sessions_table_view(client, team_with_users, queue): @pytest.mark.django_db() def test_queue_sessions_table_only_shows_team_sessions(client, team_with_users, queue): - from apps.utils.factories.experiment import ChatMessageFactory, ExperimentSessionFactory # noqa: PLC0415 - own_session = ExperimentSessionFactory.create(team=team_with_users) ChatMessageFactory.create(chat=own_session.chat) other_session = ExperimentSessionFactory.create() # different team @@ -780,8 +774,6 @@ def test_queue_sessions_table_only_shows_team_sessions(client, team_with_users, @pytest.mark.django_db() def test_queue_sessions_json_returns_external_ids(client, team_with_users, queue): - from apps.utils.factories.experiment import ChatMessageFactory, ExperimentSessionFactory # noqa: PLC0415 - sessions = ExperimentSessionFactory.create_batch(3, team=team_with_users) for s in sessions: ChatMessageFactory.create(chat=s.chat) @@ -804,8 +796,6 @@ def test_queue_sessions_json_requires_login(team_with_users, queue): @pytest.mark.django_db() def test_queue_sessions_table_excludes_sessions_without_messages(client, team_with_users, queue): - from apps.utils.factories.experiment import ChatMessageFactory, ExperimentSessionFactory # noqa: PLC0415 - session_with_messages = ExperimentSessionFactory.create(team=team_with_users) ChatMessageFactory.create(chat=session_with_messages.chat) session_without_messages = ExperimentSessionFactory.create(team=team_with_users) @@ -819,8 +809,6 @@ def test_queue_sessions_table_excludes_sessions_without_messages(client, team_wi @pytest.mark.django_db() def test_queue_sessions_json_excludes_sessions_without_messages(client, team_with_users, queue): - from apps.utils.factories.experiment import ChatMessageFactory, ExperimentSessionFactory # noqa: PLC0415 - session_with_messages = ExperimentSessionFactory.create(team=team_with_users) ChatMessageFactory.create(chat=session_with_messages.chat) ExperimentSessionFactory.create(team=team_with_users) # no messages @@ -845,24 +833,17 @@ def test_add_sessions_get_renders_filter_context(client, team_with_users, queue) @pytest.mark.django_db() def test_add_sessions_post_creates_items_from_external_ids(client, team_with_users, queue): - from apps.utils.factories.experiment import ExperimentSessionFactory # noqa: PLC0415 - sessions = ExperimentSessionFactory.create_batch(2, team=team_with_users) session_ids = ",".join(str(s.external_id) for s in sessions) url = reverse("human_annotations:queue_add_sessions", args=[team_with_users.slug, queue.pk]) response = client.post(url, {"session_ids": session_ids}) assert response.status_code == 302 assert response["Location"] == reverse("human_annotations:queue_detail", args=[team_with_users.slug, queue.pk]) - from apps.human_annotations.models import AnnotationItem # noqa: PLC0415 - assert AnnotationItem.objects.filter(queue=queue).count() == 2 @pytest.mark.django_db() def test_add_sessions_post_skips_duplicates(client, team_with_users, queue): - from apps.human_annotations.models import AnnotationItem # noqa: PLC0415 - from apps.utils.factories.experiment import ExperimentSessionFactory # noqa: PLC0415 - item = AnnotationItemFactory.create(queue=queue, team=team_with_users) existing_session = item.session new_session = ExperimentSessionFactory.create(team=team_with_users) @@ -877,16 +858,11 @@ def test_add_sessions_post_empty_redirects_with_error(client, team_with_users, q url = reverse("human_annotations:queue_add_sessions", args=[team_with_users.slug, queue.pk]) response = client.post(url, {"session_ids": ""}) assert response.status_code == 302 - from apps.human_annotations.models import AnnotationItem # noqa: PLC0415 - assert AnnotationItem.objects.filter(queue=queue).count() == 0 @pytest.mark.django_db() def test_add_sessions_post_ignores_other_team_sessions(client, team_with_users, queue): - from apps.human_annotations.models import AnnotationItem # noqa: PLC0415 - from apps.utils.factories.experiment import ExperimentSessionFactory # noqa: PLC0415 - other_session = ExperimentSessionFactory.create() # different team url = reverse("human_annotations:queue_add_sessions", args=[team_with_users.slug, queue.pk]) client.post(url, {"session_ids": str(other_session.external_id)})