gitflow-analytics 1.0.3__py3-none-any.whl → 1.3.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gitflow_analytics/_version.py +1 -1
- gitflow_analytics/classification/__init__.py +31 -0
- gitflow_analytics/classification/batch_classifier.py +752 -0
- gitflow_analytics/classification/classifier.py +464 -0
- gitflow_analytics/classification/feature_extractor.py +725 -0
- gitflow_analytics/classification/linguist_analyzer.py +574 -0
- gitflow_analytics/classification/model.py +455 -0
- gitflow_analytics/cli.py +4108 -350
- gitflow_analytics/cli_rich.py +198 -48
- gitflow_analytics/config/__init__.py +43 -0
- gitflow_analytics/config/errors.py +261 -0
- gitflow_analytics/config/loader.py +904 -0
- gitflow_analytics/config/profiles.py +264 -0
- gitflow_analytics/config/repository.py +124 -0
- gitflow_analytics/config/schema.py +441 -0
- gitflow_analytics/config/validator.py +154 -0
- gitflow_analytics/config.py +44 -508
- gitflow_analytics/core/analyzer.py +1209 -98
- gitflow_analytics/core/cache.py +1337 -29
- gitflow_analytics/core/data_fetcher.py +1193 -0
- gitflow_analytics/core/identity.py +363 -14
- gitflow_analytics/core/metrics_storage.py +526 -0
- gitflow_analytics/core/progress.py +372 -0
- gitflow_analytics/core/schema_version.py +269 -0
- gitflow_analytics/extractors/ml_tickets.py +1100 -0
- gitflow_analytics/extractors/story_points.py +8 -1
- gitflow_analytics/extractors/tickets.py +749 -11
- gitflow_analytics/identity_llm/__init__.py +6 -0
- gitflow_analytics/identity_llm/analysis_pass.py +231 -0
- gitflow_analytics/identity_llm/analyzer.py +464 -0
- gitflow_analytics/identity_llm/models.py +76 -0
- gitflow_analytics/integrations/github_integration.py +175 -11
- gitflow_analytics/integrations/jira_integration.py +461 -24
- gitflow_analytics/integrations/orchestrator.py +124 -1
- gitflow_analytics/metrics/activity_scoring.py +322 -0
- gitflow_analytics/metrics/branch_health.py +470 -0
- gitflow_analytics/metrics/dora.py +379 -20
- gitflow_analytics/models/database.py +843 -53
- gitflow_analytics/pm_framework/__init__.py +115 -0
- gitflow_analytics/pm_framework/adapters/__init__.py +50 -0
- gitflow_analytics/pm_framework/adapters/jira_adapter.py +1845 -0
- gitflow_analytics/pm_framework/base.py +406 -0
- gitflow_analytics/pm_framework/models.py +211 -0
- gitflow_analytics/pm_framework/orchestrator.py +652 -0
- gitflow_analytics/pm_framework/registry.py +333 -0
- gitflow_analytics/qualitative/__init__.py +9 -10
- gitflow_analytics/qualitative/chatgpt_analyzer.py +259 -0
- gitflow_analytics/qualitative/classifiers/__init__.py +3 -3
- gitflow_analytics/qualitative/classifiers/change_type.py +518 -244
- gitflow_analytics/qualitative/classifiers/domain_classifier.py +272 -165
- gitflow_analytics/qualitative/classifiers/intent_analyzer.py +321 -222
- gitflow_analytics/qualitative/classifiers/llm/__init__.py +35 -0
- gitflow_analytics/qualitative/classifiers/llm/base.py +193 -0
- gitflow_analytics/qualitative/classifiers/llm/batch_processor.py +383 -0
- gitflow_analytics/qualitative/classifiers/llm/cache.py +479 -0
- gitflow_analytics/qualitative/classifiers/llm/cost_tracker.py +435 -0
- gitflow_analytics/qualitative/classifiers/llm/openai_client.py +403 -0
- gitflow_analytics/qualitative/classifiers/llm/prompts.py +373 -0
- gitflow_analytics/qualitative/classifiers/llm/response_parser.py +287 -0
- gitflow_analytics/qualitative/classifiers/llm_commit_classifier.py +607 -0
- gitflow_analytics/qualitative/classifiers/risk_analyzer.py +215 -189
- gitflow_analytics/qualitative/core/__init__.py +4 -4
- gitflow_analytics/qualitative/core/llm_fallback.py +239 -235
- gitflow_analytics/qualitative/core/nlp_engine.py +157 -148
- gitflow_analytics/qualitative/core/pattern_cache.py +214 -192
- gitflow_analytics/qualitative/core/processor.py +381 -248
- gitflow_analytics/qualitative/enhanced_analyzer.py +2236 -0
- gitflow_analytics/qualitative/example_enhanced_usage.py +420 -0
- gitflow_analytics/qualitative/models/__init__.py +7 -7
- gitflow_analytics/qualitative/models/schemas.py +155 -121
- gitflow_analytics/qualitative/utils/__init__.py +4 -4
- gitflow_analytics/qualitative/utils/batch_processor.py +136 -123
- gitflow_analytics/qualitative/utils/cost_tracker.py +142 -140
- gitflow_analytics/qualitative/utils/metrics.py +172 -158
- gitflow_analytics/qualitative/utils/text_processing.py +146 -104
- gitflow_analytics/reports/__init__.py +100 -0
- gitflow_analytics/reports/analytics_writer.py +539 -14
- gitflow_analytics/reports/base.py +648 -0
- gitflow_analytics/reports/branch_health_writer.py +322 -0
- gitflow_analytics/reports/classification_writer.py +924 -0
- gitflow_analytics/reports/cli_integration.py +427 -0
- gitflow_analytics/reports/csv_writer.py +1676 -212
- gitflow_analytics/reports/data_models.py +504 -0
- gitflow_analytics/reports/database_report_generator.py +427 -0
- gitflow_analytics/reports/example_usage.py +344 -0
- gitflow_analytics/reports/factory.py +499 -0
- gitflow_analytics/reports/formatters.py +698 -0
- gitflow_analytics/reports/html_generator.py +1116 -0
- gitflow_analytics/reports/interfaces.py +489 -0
- gitflow_analytics/reports/json_exporter.py +2770 -0
- gitflow_analytics/reports/narrative_writer.py +2287 -158
- gitflow_analytics/reports/story_point_correlation.py +1144 -0
- gitflow_analytics/reports/weekly_trends_writer.py +389 -0
- gitflow_analytics/training/__init__.py +5 -0
- gitflow_analytics/training/model_loader.py +377 -0
- gitflow_analytics/training/pipeline.py +550 -0
- gitflow_analytics/tui/__init__.py +1 -1
- gitflow_analytics/tui/app.py +129 -126
- gitflow_analytics/tui/screens/__init__.py +3 -3
- gitflow_analytics/tui/screens/analysis_progress_screen.py +188 -179
- gitflow_analytics/tui/screens/configuration_screen.py +154 -178
- gitflow_analytics/tui/screens/loading_screen.py +100 -110
- gitflow_analytics/tui/screens/main_screen.py +89 -72
- gitflow_analytics/tui/screens/results_screen.py +305 -281
- gitflow_analytics/tui/widgets/__init__.py +2 -2
- gitflow_analytics/tui/widgets/data_table.py +67 -69
- gitflow_analytics/tui/widgets/export_modal.py +76 -76
- gitflow_analytics/tui/widgets/progress_widget.py +41 -46
- gitflow_analytics-1.3.6.dist-info/METADATA +1015 -0
- gitflow_analytics-1.3.6.dist-info/RECORD +122 -0
- gitflow_analytics-1.0.3.dist-info/METADATA +0 -490
- gitflow_analytics-1.0.3.dist-info/RECORD +0 -62
- {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.6.dist-info}/WHEEL +0 -0
- {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.6.dist-info}/entry_points.txt +0 -0
- {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.6.dist-info}/licenses/LICENSE +0 -0
- {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.6.dist-info}/top_level.txt +0 -0
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import time
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Any, Optional
|
|
6
6
|
|
|
7
|
-
from textual.widgets import Header, Footer, Label, Static, LoadingIndicator
|
|
8
|
-
from textual.containers import Container, Vertical, Horizontal, Center
|
|
9
|
-
from textual.screen import Screen
|
|
10
7
|
from textual.binding import Binding
|
|
8
|
+
from textual.containers import Center, Container, Vertical
|
|
11
9
|
from textual.message import Message
|
|
12
|
-
from
|
|
13
|
-
from
|
|
10
|
+
from textual.screen import Screen
|
|
11
|
+
from textual.widgets import Footer, Header, Label, LoadingIndicator, Static
|
|
14
12
|
|
|
15
13
|
from ..widgets.progress_widget import AnalysisProgressWidget
|
|
16
14
|
|
|
@@ -18,146 +16,141 @@ from ..widgets.progress_widget import AnalysisProgressWidget
|
|
|
18
16
|
class LoadingScreen(Screen):
|
|
19
17
|
"""
|
|
20
18
|
Loading screen displayed during application startup and heavy initialization.
|
|
21
|
-
|
|
19
|
+
|
|
22
20
|
WHY: The TUI application needs to load configurations, spaCy models, and other
|
|
23
21
|
heavy resources during startup. This screen provides user feedback about the
|
|
24
22
|
loading process instead of showing a black screen, improving user experience.
|
|
25
|
-
|
|
23
|
+
|
|
26
24
|
DESIGN DECISION: Uses a combination of progress indicators and status messages
|
|
27
25
|
to show both overall progress and specific loading steps. This keeps users
|
|
28
26
|
informed about what's happening and that the application is responsive.
|
|
29
27
|
"""
|
|
30
|
-
|
|
28
|
+
|
|
31
29
|
BINDINGS = [
|
|
32
30
|
Binding("ctrl+c", "cancel", "Cancel Loading"),
|
|
33
31
|
Binding("escape", "cancel", "Cancel Loading"),
|
|
34
32
|
]
|
|
35
|
-
|
|
33
|
+
|
|
36
34
|
def __init__(
|
|
37
35
|
self,
|
|
38
36
|
loading_message: str = "Initializing GitFlow Analytics...",
|
|
39
37
|
*,
|
|
40
38
|
name: Optional[str] = None,
|
|
41
|
-
id: Optional[str] = None
|
|
39
|
+
id: Optional[str] = None,
|
|
42
40
|
) -> None:
|
|
43
41
|
super().__init__(name=name, id=id)
|
|
44
42
|
self.loading_message = loading_message
|
|
45
43
|
self.loading_task: Optional[asyncio.Task] = None
|
|
46
44
|
self.start_time = time.time()
|
|
47
45
|
self.cancelled = False
|
|
48
|
-
|
|
46
|
+
|
|
49
47
|
def compose(self):
|
|
50
48
|
"""Compose the loading screen with progress indicators."""
|
|
51
49
|
yield Header()
|
|
52
|
-
|
|
50
|
+
|
|
53
51
|
with Container(id="loading-container"):
|
|
54
52
|
# Main loading title
|
|
55
53
|
yield Label("GitFlow Analytics", classes="screen-title")
|
|
56
54
|
yield Label("Developer Productivity Analysis", classes="help-text center")
|
|
57
|
-
|
|
55
|
+
|
|
58
56
|
# Loading animation and message
|
|
59
|
-
with Center():
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
yield
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
yield Static("⏳ Loading configuration...", id="step-config")
|
|
82
|
-
yield Static("⏳ Preparing analysis engine...", id="step-engine")
|
|
83
|
-
yield Static("⏳ Loading NLP models...", id="step-nlp")
|
|
84
|
-
yield Static("⏳ Finalizing setup...", id="step-finalize")
|
|
85
|
-
|
|
57
|
+
with Center(), Vertical(id="loading-content"):
|
|
58
|
+
yield LoadingIndicator(id="main-spinner")
|
|
59
|
+
yield Label(self.loading_message, classes="center", id="loading-message")
|
|
60
|
+
|
|
61
|
+
# Overall progress bar
|
|
62
|
+
yield AnalysisProgressWidget("Startup Progress", total=100.0, id="startup-progress")
|
|
63
|
+
|
|
64
|
+
# Status messages
|
|
65
|
+
with Container(classes="status-panel"):
|
|
66
|
+
yield Label("Status", classes="panel-title")
|
|
67
|
+
yield Static("Starting up...", id="status-message")
|
|
68
|
+
|
|
69
|
+
# Loading steps indicators
|
|
70
|
+
with Container(classes="stats-panel"):
|
|
71
|
+
yield Label("Loading Steps", classes="panel-title")
|
|
72
|
+
with Vertical(id="loading-steps"):
|
|
73
|
+
yield Static("⏳ Initializing application...", id="step-init")
|
|
74
|
+
yield Static("⏳ Loading configuration...", id="step-config")
|
|
75
|
+
yield Static("⏳ Preparing analysis engine...", id="step-engine")
|
|
76
|
+
yield Static("⏳ Loading NLP models...", id="step-nlp")
|
|
77
|
+
yield Static("⏳ Finalizing setup...", id="step-finalize")
|
|
78
|
+
|
|
86
79
|
yield Footer()
|
|
87
|
-
|
|
80
|
+
|
|
88
81
|
def on_mount(self) -> None:
|
|
89
82
|
"""Start loading process when screen mounts."""
|
|
90
83
|
self.loading_task = asyncio.create_task(self._simulate_loading())
|
|
91
|
-
|
|
84
|
+
|
|
92
85
|
async def _simulate_loading(self) -> None:
|
|
93
86
|
"""
|
|
94
87
|
Simulate the loading process with progress updates.
|
|
95
|
-
|
|
88
|
+
|
|
96
89
|
WHY: This provides visual feedback during startup initialization.
|
|
97
90
|
In practice, this would be replaced by actual initialization calls.
|
|
98
91
|
"""
|
|
99
92
|
progress_widget = self.query_one("#startup-progress", AnalysisProgressWidget)
|
|
100
93
|
status_message = self.query_one("#status-message", Static)
|
|
101
|
-
|
|
94
|
+
|
|
102
95
|
try:
|
|
103
96
|
# Step 1: Initialize application (20%)
|
|
104
97
|
await self._update_step("step-init", "✅ Application initialized", "success")
|
|
105
98
|
status_message.update("Initializing core components...")
|
|
106
99
|
progress_widget.update_progress(20, "Core components ready")
|
|
107
100
|
await asyncio.sleep(0.3)
|
|
108
|
-
|
|
101
|
+
|
|
109
102
|
if self.cancelled:
|
|
110
103
|
return
|
|
111
|
-
|
|
104
|
+
|
|
112
105
|
# Step 2: Load configuration (40%)
|
|
113
106
|
await self._update_step("step-config", "✅ Configuration loaded", "success")
|
|
114
107
|
status_message.update("Loading configuration files...")
|
|
115
108
|
progress_widget.update_progress(40, "Configuration loaded")
|
|
116
109
|
await asyncio.sleep(0.5)
|
|
117
|
-
|
|
110
|
+
|
|
118
111
|
if self.cancelled:
|
|
119
112
|
return
|
|
120
|
-
|
|
113
|
+
|
|
121
114
|
# Step 3: Prepare analysis engine (60%)
|
|
122
115
|
await self._update_step("step-engine", "✅ Analysis engine ready", "success")
|
|
123
116
|
status_message.update("Preparing Git analysis engine...")
|
|
124
117
|
progress_widget.update_progress(60, "Analysis engine initialized")
|
|
125
118
|
await asyncio.sleep(0.4)
|
|
126
|
-
|
|
119
|
+
|
|
127
120
|
if self.cancelled:
|
|
128
121
|
return
|
|
129
|
-
|
|
122
|
+
|
|
130
123
|
# Step 4: Load NLP models (85%) - This is the heavy operation
|
|
131
124
|
await self._update_step("step-nlp", "⏳ Loading spaCy models...", "warning")
|
|
132
125
|
status_message.update("Loading natural language processing models...")
|
|
133
126
|
progress_widget.update_progress(70, "Loading spaCy models...")
|
|
134
127
|
await asyncio.sleep(1.2) # Simulate spaCy model loading time
|
|
135
|
-
|
|
128
|
+
|
|
136
129
|
if self.cancelled:
|
|
137
130
|
return
|
|
138
|
-
|
|
131
|
+
|
|
139
132
|
await self._update_step("step-nlp", "✅ NLP models loaded", "success")
|
|
140
133
|
progress_widget.update_progress(85, "NLP models ready")
|
|
141
|
-
|
|
134
|
+
|
|
142
135
|
# Step 5: Finalize setup (100%)
|
|
143
136
|
await self._update_step("step-finalize", "✅ Setup complete", "success")
|
|
144
137
|
status_message.update("Finalizing application setup...")
|
|
145
138
|
progress_widget.update_progress(100, "GitFlow Analytics ready!")
|
|
146
139
|
await asyncio.sleep(0.3)
|
|
147
|
-
|
|
140
|
+
|
|
148
141
|
# Show completion message briefly
|
|
149
142
|
loading_message = self.query_one("#loading-message", Label)
|
|
150
143
|
loading_message.update("Loading complete! Starting application...")
|
|
151
|
-
|
|
144
|
+
|
|
152
145
|
elapsed_time = time.time() - self.start_time
|
|
153
146
|
status_message.update(f"Ready! Loaded in {elapsed_time:.1f} seconds")
|
|
154
|
-
|
|
147
|
+
|
|
155
148
|
# Wait a moment to show completion
|
|
156
149
|
await asyncio.sleep(0.8)
|
|
157
|
-
|
|
150
|
+
|
|
158
151
|
# Signal that loading is complete
|
|
159
152
|
self.app.post_message(self.LoadingComplete())
|
|
160
|
-
|
|
153
|
+
|
|
161
154
|
except asyncio.CancelledError:
|
|
162
155
|
progress_widget.update_progress(0, "Loading cancelled")
|
|
163
156
|
status_message.update("Loading cancelled by user")
|
|
@@ -165,73 +158,75 @@ class LoadingScreen(Screen):
|
|
|
165
158
|
progress_widget.update_progress(0, f"Error: {str(e)[:50]}...")
|
|
166
159
|
status_message.update(f"Loading failed: {e}")
|
|
167
160
|
self.app.notify(f"Loading failed: {e}", severity="error")
|
|
168
|
-
|
|
161
|
+
|
|
169
162
|
async def _update_step(self, step_id: str, message: str, status: str) -> None:
|
|
170
163
|
"""
|
|
171
164
|
Update a loading step with status.
|
|
172
|
-
|
|
165
|
+
|
|
173
166
|
@param step_id: ID of the step element to update
|
|
174
167
|
@param message: Status message to display
|
|
175
168
|
@param status: Status type (success, warning, error)
|
|
176
169
|
"""
|
|
177
170
|
step_element = self.query_one(f"#{step_id}", Static)
|
|
178
171
|
step_element.update(message)
|
|
179
|
-
|
|
172
|
+
|
|
180
173
|
# Apply appropriate styling based on status
|
|
181
174
|
step_element.remove_class("success", "warning", "error")
|
|
182
175
|
step_element.add_class(status)
|
|
183
|
-
|
|
176
|
+
|
|
184
177
|
def update_loading_message(self, message: str) -> None:
|
|
185
178
|
"""
|
|
186
179
|
Update the main loading message.
|
|
187
|
-
|
|
180
|
+
|
|
188
181
|
@param message: New loading message to display
|
|
189
182
|
"""
|
|
190
183
|
try:
|
|
191
184
|
loading_message = self.query_one("#loading-message", Label)
|
|
192
185
|
loading_message.update(message)
|
|
193
|
-
except:
|
|
186
|
+
except Exception:
|
|
194
187
|
pass # Ignore if element not found
|
|
195
|
-
|
|
188
|
+
|
|
196
189
|
def update_progress(self, percentage: float, status: str) -> None:
|
|
197
190
|
"""
|
|
198
191
|
Update the overall progress bar.
|
|
199
|
-
|
|
192
|
+
|
|
200
193
|
@param percentage: Progress percentage (0-100)
|
|
201
194
|
@param status: Status message to display
|
|
202
195
|
"""
|
|
203
196
|
try:
|
|
204
197
|
progress_widget = self.query_one("#startup-progress", AnalysisProgressWidget)
|
|
205
198
|
progress_widget.update_progress(percentage, status)
|
|
206
|
-
except:
|
|
199
|
+
except Exception:
|
|
207
200
|
pass # Ignore if element not found
|
|
208
|
-
|
|
201
|
+
|
|
209
202
|
def update_status(self, status: str) -> None:
|
|
210
203
|
"""
|
|
211
204
|
Update the status message.
|
|
212
|
-
|
|
205
|
+
|
|
213
206
|
@param status: Status message to display
|
|
214
207
|
"""
|
|
215
208
|
try:
|
|
216
209
|
status_message = self.query_one("#status-message", Static)
|
|
217
210
|
status_message.update(status)
|
|
218
|
-
except:
|
|
211
|
+
except Exception:
|
|
219
212
|
pass # Ignore if element not found
|
|
220
|
-
|
|
213
|
+
|
|
221
214
|
def action_cancel(self) -> None:
|
|
222
215
|
"""Cancel the loading process."""
|
|
223
216
|
self.cancelled = True
|
|
224
217
|
if self.loading_task and not self.loading_task.done():
|
|
225
218
|
self.loading_task.cancel()
|
|
226
219
|
self.app.post_message(self.LoadingCancelled())
|
|
227
|
-
|
|
220
|
+
|
|
228
221
|
class LoadingComplete(Message):
|
|
229
222
|
"""Message sent when loading is complete."""
|
|
223
|
+
|
|
230
224
|
def __init__(self) -> None:
|
|
231
225
|
super().__init__()
|
|
232
|
-
|
|
226
|
+
|
|
233
227
|
class LoadingCancelled(Message):
|
|
234
228
|
"""Message sent when loading is cancelled."""
|
|
229
|
+
|
|
235
230
|
def __init__(self) -> None:
|
|
236
231
|
super().__init__()
|
|
237
232
|
|
|
@@ -239,110 +234,104 @@ class LoadingScreen(Screen):
|
|
|
239
234
|
class InitializationLoadingScreen(LoadingScreen):
|
|
240
235
|
"""
|
|
241
236
|
Specialized loading screen for real application initialization.
|
|
242
|
-
|
|
237
|
+
|
|
243
238
|
WHY: This version of the loading screen performs actual initialization
|
|
244
239
|
tasks instead of just simulating them, providing real progress feedback
|
|
245
240
|
during startup.
|
|
246
241
|
"""
|
|
247
|
-
|
|
248
|
-
def __init__(
|
|
249
|
-
self,
|
|
250
|
-
config_loader_func=None,
|
|
251
|
-
nlp_init_func=None,
|
|
252
|
-
*args,
|
|
253
|
-
**kwargs
|
|
254
|
-
) -> None:
|
|
242
|
+
|
|
243
|
+
def __init__(self, config_loader_func=None, nlp_init_func=None, *args, **kwargs) -> None:
|
|
255
244
|
super().__init__(*args, **kwargs)
|
|
256
245
|
self.config_loader_func = config_loader_func
|
|
257
246
|
self.nlp_init_func = nlp_init_func
|
|
258
247
|
self.initialization_data = {}
|
|
259
|
-
|
|
248
|
+
|
|
260
249
|
async def _simulate_loading(self) -> None:
|
|
261
250
|
"""
|
|
262
251
|
Perform actual initialization tasks with progress updates.
|
|
263
|
-
|
|
252
|
+
|
|
264
253
|
WHY: This replaces the simulation with real initialization work,
|
|
265
254
|
allowing the loading screen to show progress of actual operations.
|
|
266
255
|
"""
|
|
267
256
|
progress_widget = self.query_one("#startup-progress", AnalysisProgressWidget)
|
|
268
257
|
status_message = self.query_one("#status-message", Static)
|
|
269
|
-
|
|
258
|
+
|
|
270
259
|
try:
|
|
271
260
|
# Step 1: Initialize application (20%)
|
|
272
261
|
await self._update_step("step-init", "✅ Application initialized", "success")
|
|
273
262
|
status_message.update("Initializing core components...")
|
|
274
263
|
progress_widget.update_progress(20, "Core components ready")
|
|
275
264
|
await asyncio.sleep(0.1)
|
|
276
|
-
|
|
265
|
+
|
|
277
266
|
if self.cancelled:
|
|
278
267
|
return
|
|
279
|
-
|
|
268
|
+
|
|
280
269
|
# Step 2: Load configuration (40%)
|
|
281
270
|
status_message.update("Discovering configuration files...")
|
|
282
271
|
await self._update_step("step-config", "⏳ Loading configuration...", "warning")
|
|
283
|
-
|
|
272
|
+
|
|
284
273
|
if self.config_loader_func:
|
|
285
274
|
config_result = await asyncio.get_event_loop().run_in_executor(
|
|
286
275
|
None, self.config_loader_func
|
|
287
276
|
)
|
|
288
|
-
self.initialization_data[
|
|
289
|
-
|
|
277
|
+
self.initialization_data["config"] = config_result
|
|
278
|
+
|
|
290
279
|
await self._update_step("step-config", "✅ Configuration loaded", "success")
|
|
291
280
|
progress_widget.update_progress(40, "Configuration ready")
|
|
292
281
|
await asyncio.sleep(0.1)
|
|
293
|
-
|
|
282
|
+
|
|
294
283
|
if self.cancelled:
|
|
295
284
|
return
|
|
296
|
-
|
|
285
|
+
|
|
297
286
|
# Step 3: Prepare analysis engine (60%)
|
|
298
287
|
await self._update_step("step-engine", "✅ Analysis engine ready", "success")
|
|
299
288
|
status_message.update("Preparing Git analysis components...")
|
|
300
289
|
progress_widget.update_progress(60, "Analysis engine initialized")
|
|
301
290
|
await asyncio.sleep(0.2)
|
|
302
|
-
|
|
291
|
+
|
|
303
292
|
if self.cancelled:
|
|
304
293
|
return
|
|
305
|
-
|
|
294
|
+
|
|
306
295
|
# Step 4: Load NLP models (85%) - Heavy operation
|
|
307
|
-
config = self.initialization_data.get(
|
|
308
|
-
if config and getattr(config,
|
|
296
|
+
config = self.initialization_data.get("config")
|
|
297
|
+
if config and getattr(config, "qualitative", None) and config.qualitative.enabled:
|
|
309
298
|
await self._update_step("step-nlp", "⏳ Loading spaCy models...", "warning")
|
|
310
299
|
status_message.update("Loading natural language processing models...")
|
|
311
300
|
progress_widget.update_progress(70, "Loading spaCy models...")
|
|
312
|
-
|
|
301
|
+
|
|
313
302
|
if self.nlp_init_func:
|
|
314
303
|
nlp_result = await asyncio.get_event_loop().run_in_executor(
|
|
315
304
|
None, self.nlp_init_func, config
|
|
316
305
|
)
|
|
317
|
-
self.initialization_data[
|
|
318
|
-
|
|
306
|
+
self.initialization_data["nlp"] = nlp_result
|
|
307
|
+
|
|
319
308
|
await self._update_step("step-nlp", "✅ NLP models loaded", "success")
|
|
320
309
|
progress_widget.update_progress(85, "NLP models ready")
|
|
321
310
|
else:
|
|
322
311
|
await self._update_step("step-nlp", "⏸️ NLP models skipped", "warning")
|
|
323
312
|
progress_widget.update_progress(85, "NLP models skipped (qualitative disabled)")
|
|
324
|
-
|
|
313
|
+
|
|
325
314
|
if self.cancelled:
|
|
326
315
|
return
|
|
327
|
-
|
|
316
|
+
|
|
328
317
|
# Step 5: Finalize setup (100%)
|
|
329
318
|
await self._update_step("step-finalize", "✅ Setup complete", "success")
|
|
330
319
|
status_message.update("Finalizing application setup...")
|
|
331
320
|
progress_widget.update_progress(100, "GitFlow Analytics ready!")
|
|
332
|
-
|
|
321
|
+
|
|
333
322
|
# Show completion message briefly
|
|
334
323
|
loading_message = self.query_one("#loading-message", Label)
|
|
335
324
|
loading_message.update("Initialization complete! Starting application...")
|
|
336
|
-
|
|
325
|
+
|
|
337
326
|
elapsed_time = time.time() - self.start_time
|
|
338
327
|
status_message.update(f"Ready! Initialized in {elapsed_time:.1f} seconds")
|
|
339
|
-
|
|
328
|
+
|
|
340
329
|
# Wait a moment to show completion
|
|
341
330
|
await asyncio.sleep(0.5)
|
|
342
|
-
|
|
331
|
+
|
|
343
332
|
# Signal that loading is complete with initialization data
|
|
344
333
|
self.app.post_message(self.InitializationComplete(self.initialization_data))
|
|
345
|
-
|
|
334
|
+
|
|
346
335
|
except asyncio.CancelledError:
|
|
347
336
|
progress_widget.update_progress(0, "Initialization cancelled")
|
|
348
337
|
status_message.update("Initialization cancelled by user")
|
|
@@ -350,9 +339,10 @@ class InitializationLoadingScreen(LoadingScreen):
|
|
|
350
339
|
progress_widget.update_progress(0, f"Error: {str(e)[:50]}...")
|
|
351
340
|
status_message.update(f"Initialization failed: {e}")
|
|
352
341
|
self.app.notify(f"Initialization failed: {e}", severity="error")
|
|
353
|
-
|
|
342
|
+
|
|
354
343
|
class InitializationComplete(Message):
|
|
355
344
|
"""Message sent when initialization is complete with data."""
|
|
356
|
-
|
|
345
|
+
|
|
346
|
+
def __init__(self, data: dict[str, Any]) -> None:
|
|
357
347
|
super().__init__()
|
|
358
|
-
self.data = data
|
|
348
|
+
self.data = data
|