• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

liqd / roots / 22072536647

16 Feb 2026 05:41PM UTC coverage: 42.093%. First build
22072536647

Pull #59

github

Pull Request #59: apps/summerization: Integrate Document Summary into Workflow

51 of 314 new or added lines in 7 files covered. (16.24%)

3564 of 8467 relevant lines covered (42.09%)

0.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/apps/summarization/views.py
1
import json
×
2
from types import SimpleNamespace
×
3

NEW
4
from django.shortcuts import render
×
5
from django.views import View
×
6

×
NEW
7
from .pydantic_models import DocumentInputItem
×
8
from .pydantic_models import ProjectSummaryResponse
×
NEW
9
from .services import AIService
×
10
from .services import SummaryRequest
11

12

×
13
class SummarizationTestView(View):
14
    """Simple test view for summarization service."""
15

×
16
    def get(self, request):
17
        """Display test form."""
18
        default_prompt = SummaryRequest.DEFAULT_PROMPT
×
19
        context = {
×
20
            "default_prompt": default_prompt,
21
        }
22
        return render(request, "summarization/test.html", context)
×
23

NEW
24
    def _handle_text_request(
×
25
        self, text: str, prompt: str, provider_handle: str | None
26
    ) -> tuple[ProjectSummaryResponse | None, int, str | None]:
27
        """Handle text-only summarization."""
NEW
28
        try:
×
29
            service = AIService(provider_handle=provider_handle)
NEW
30
            response = service.summarize(
×
NEW
31
                text=text,
×
32
                prompt=prompt if prompt else None,
33
                result_type=ProjectSummaryResponse,
34
            )
35
            return response, len(text), None
NEW
36
        except Exception as e:
×
37
            return None, 0, str(e)
NEW
38

×
NEW
39
    def _extract_project_from_json(self, text: str):
×
NEW
40
        """Extract project information from JSON text if available."""
×
NEW
41
        try:
×
NEW
42
            data = json.loads(text)
×
NEW
43
            if isinstance(data, dict) and "project" in data:
×
44
                project_data = data["project"]
NEW
45
                # Create a simple mock project object with needed attributes
×
46
                project = SimpleNamespace()
NEW
47
                project.slug = project_data.get("slug", "test-project")
×
48
                project.pk = project_data.get("id", 1)
49
                project.result = project_data.get("result", "")
50
                project.name = project_data.get("name", "Test Project")
NEW
51

×
NEW
52
                # Create mock organisation
×
NEW
53
                org = SimpleNamespace()
×
54
                org_data = project_data.get("organisation", "test-org")
55
                if isinstance(org_data, dict):
56
                    org.slug = org_data.get("slug", "test-org")
57
                else:
NEW
58
                    # If organisation is just a string (name), use it as slug
×
59
                    org.slug = str(org_data).lower().replace(" ", "-")
60
                project.organisation = org
61

NEW
62
                # Mock get_absolute_url method
×
NEW
63
                def get_absolute_url():
×
NEW
64
                    return f"/projects/{project.slug}/"
×
65

NEW
66
                project.get_absolute_url = get_absolute_url
×
67

68
                # Mock modules queryset for _summary_section.html
69
                # The template uses project.modules|get_module_by_id filter
NEW
70
                class MockModules:
×
NEW
71
                    def filter(self, id=None):
×
NEW
72
                        return self
×
73

74
                    def first(self):
75
                        return None
76

NEW
77
                project.modules = MockModules()
×
NEW
78

×
NEW
79
                return project
×
80
        except (json.JSONDecodeError, KeyError, AttributeError):
81
            pass
×
82
        return None
83

×
84
    def post(self, request):
×
85
        """Process summarization request."""
×
NEW
86
        text = request.POST.get("text", "")
×
NEW
87
        prompt = request.POST.get("prompt", "")
×
88
        provider_handle = request.POST.get("provider", None)
89

×
90
        context = {
91
            "text": text,
92
            "prompt": prompt,
93
            "default_prompt": SummaryRequest.DEFAULT_PROMPT,
94
            "provider": provider_handle or "ovhcloud",
95
            "summary_response": None,
96
            "error": None,
97
            "original_length": 0,
98
            "project": None,
NEW
99
        }
×
NEW
100

×
NEW
101
        if text:
×
NEW
102
            # Try to extract project from JSON
×
103
            project = self._extract_project_from_json(text)
NEW
104
            if project:
×
NEW
105
                context["project"] = project
×
106

107
            response, original_length, error = self._handle_text_request(
NEW
108
                text, prompt, provider_handle
×
NEW
109
            )
×
NEW
110
            context["summary_response"] = response
×
NEW
111
            context["original_length"] = original_length
×
NEW
112
            if error:
×
NEW
113
                context["error"] = error
×
114

115
        return render(request, "summarization/test.html", context)
NEW
116

×
NEW
117

×
NEW
118
class DocumentSummarizationTestView(View):
×
NEW
119
    """Test view for document summarization with handles."""
×
120

NEW
121
    def get(self, request):
×
122
        """Display test form."""
123
        context = {}
NEW
124
        return render(request, "summarization/test_documents.html", context)
×
125

126
    def post(self, request):
NEW
127
        """Process document summarization request."""
×
128
        prompt = request.POST.get("prompt", "")
NEW
129
        provider_handle = request.POST.get("provider", None)
×
NEW
130
        if provider_handle == "":
×
131
            provider_handle = None
NEW
132
        documents_json = request.POST.get("documents", "")
×
133

NEW
134
        context = {
×
NEW
135
            "prompt": prompt,
×
NEW
136
            "provider": provider_handle or "ovhcloud",
×
NEW
137
            "documents_json": documents_json,
×
NEW
138
            "summary_response": None,
×
139
            "error": None,
NEW
140
        }
×
141

142
        if documents_json:
143
            try:
144
                import json
145

146
                # Parse JSON input
147
                documents_data = json.loads(documents_json)
NEW
148

×
149
                # Convert to list of DocumentInputItem
×
NEW
150
                if isinstance(documents_data, dict):
×
151
                    # If it's a dict, convert to list format
152
                    documents = [
NEW
153
                        DocumentInputItem(handle=handle, url=url)
×
154
                        for handle, url in documents_data.items()
155
                    ]
NEW
156
                elif isinstance(documents_data, list):
×
157
                    # If it's already a list
NEW
158
                    documents = [
×
159
                        DocumentInputItem(**doc) if isinstance(doc, dict) else doc
160
                        for doc in documents_data
161
                    ]
NEW
162
                else:
×
163
                    raise ValueError("Documents must be a dict or list")
NEW
164

×
165
                # Process documents
166
                service = AIService(document_provider_handle=provider_handle)
167
                response = service.request_vision(
168
                    documents=documents,
NEW
169
                    prompt=prompt if prompt else None,
×
170
                )
171
                context["summary_response"] = response
NEW
172

×
NEW
173
            except json.JSONDecodeError as e:
×
174
                context["error"] = f"Invalid JSON: {str(e)}"
175
            except Exception as e:
176
                context["error"] = str(e)
177
        else:
×
178
            context["error"] = "Please provide documents in JSON format"
NEW
179

×
NEW
180
        return render(request, "summarization/test_documents.html", context)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc