gitflow-analytics 3.6.2__py3-none-any.whl → 3.7.0__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.
Files changed (26) hide show
  1. gitflow_analytics/__init__.py +8 -12
  2. gitflow_analytics/_version.py +1 -1
  3. gitflow_analytics/cli.py +151 -170
  4. gitflow_analytics/cli_wizards/install_wizard.py +5 -5
  5. gitflow_analytics/models/database.py +229 -8
  6. gitflow_analytics/security/reports/__init__.py +5 -0
  7. gitflow_analytics/security/reports/security_report.py +358 -0
  8. {gitflow_analytics-3.6.2.dist-info → gitflow_analytics-3.7.0.dist-info}/METADATA +2 -4
  9. {gitflow_analytics-3.6.2.dist-info → gitflow_analytics-3.7.0.dist-info}/RECORD +13 -24
  10. gitflow_analytics/tui/__init__.py +0 -5
  11. gitflow_analytics/tui/app.py +0 -726
  12. gitflow_analytics/tui/progress_adapter.py +0 -313
  13. gitflow_analytics/tui/screens/__init__.py +0 -8
  14. gitflow_analytics/tui/screens/analysis_progress_screen.py +0 -857
  15. gitflow_analytics/tui/screens/configuration_screen.py +0 -523
  16. gitflow_analytics/tui/screens/loading_screen.py +0 -348
  17. gitflow_analytics/tui/screens/main_screen.py +0 -321
  18. gitflow_analytics/tui/screens/results_screen.py +0 -735
  19. gitflow_analytics/tui/widgets/__init__.py +0 -7
  20. gitflow_analytics/tui/widgets/data_table.py +0 -255
  21. gitflow_analytics/tui/widgets/export_modal.py +0 -301
  22. gitflow_analytics/tui/widgets/progress_widget.py +0 -187
  23. {gitflow_analytics-3.6.2.dist-info → gitflow_analytics-3.7.0.dist-info}/WHEEL +0 -0
  24. {gitflow_analytics-3.6.2.dist-info → gitflow_analytics-3.7.0.dist-info}/entry_points.txt +0 -0
  25. {gitflow_analytics-3.6.2.dist-info → gitflow_analytics-3.7.0.dist-info}/licenses/LICENSE +0 -0
  26. {gitflow_analytics-3.6.2.dist-info → gitflow_analytics-3.7.0.dist-info}/top_level.txt +0 -0
@@ -1,187 +0,0 @@
1
- """Progress widget with ETA for GitFlow Analytics TUI."""
2
-
3
- import time
4
- from typing import Optional
5
-
6
- from textual.containers import Container
7
- from textual.reactive import reactive
8
- from textual.widgets import Label, ProgressBar
9
-
10
-
11
- class AnalysisProgressWidget(Container):
12
- """
13
- Custom progress widget that shows progress with ETA calculation.
14
-
15
- WHY: Standard progress bars don't provide time estimates which are crucial
16
- for long-running analysis operations. This widget combines progress tracking
17
- with ETA calculations to give users better feedback.
18
-
19
- DESIGN DECISION: Uses reactive attributes for real-time updates and
20
- calculates ETA based on average processing speed rather than simple linear
21
- extrapolation for more accurate estimates.
22
- """
23
-
24
- DEFAULT_CSS = """
25
- AnalysisProgressWidget {
26
- height: auto;
27
- border: solid $primary;
28
- margin: 1;
29
- padding: 1;
30
- }
31
-
32
- .progress-title {
33
- text-style: bold;
34
- color: $primary;
35
- margin-bottom: 1;
36
- }
37
-
38
- .progress-status {
39
- color: $text;
40
- margin-top: 1;
41
- }
42
-
43
- .progress-eta {
44
- color: $accent;
45
- text-style: italic;
46
- }
47
- """
48
-
49
- progress = reactive(0.0)
50
- total = reactive(100.0)
51
- status_text = reactive("Initializing...")
52
-
53
- def __init__(
54
- self,
55
- title: str,
56
- total: float = 100.0,
57
- *,
58
- name: Optional[str] = None,
59
- id: Optional[str] = None,
60
- classes: Optional[str] = None,
61
- ) -> None:
62
- super().__init__(name=name, id=id, classes=classes)
63
- self.title = title
64
- self.total = total
65
- self.start_time = time.time()
66
- self.last_update_time = time.time()
67
- self.progress_history = []
68
-
69
- def compose(self):
70
- """Compose the progress widget."""
71
- yield Label(self.title, classes="progress-title")
72
- yield ProgressBar(total=self.total, id="progress-bar")
73
- yield Label(self.status_text, classes="progress-status", id="status-label")
74
- yield Label("", classes="progress-eta", id="eta-label")
75
-
76
- def update_progress(self, value: float, status: str = "") -> None:
77
- """
78
- Update progress and status with ETA calculation.
79
-
80
- WHY: Provides comprehensive progress updates including time estimates
81
- which are essential for user experience during long operations.
82
-
83
- @param value: Current progress value
84
- @param status: Status message to display
85
- """
86
- current_time = time.time()
87
-
88
- # Update reactive values
89
- self.progress = value
90
- if status:
91
- self.status_text = status
92
-
93
- # Update progress bar
94
- progress_bar = self.query_one("#progress-bar", ProgressBar)
95
- progress_bar.update(progress=value)
96
-
97
- # Update status label
98
- status_label = self.query_one("#status-label", Label)
99
- status_label.update(status)
100
-
101
- # Calculate and update ETA
102
- eta_text = self._calculate_eta(value, current_time)
103
- eta_label = self.query_one("#eta-label", Label)
104
- eta_label.update(eta_text)
105
-
106
- # Store progress history for better ETA calculation
107
- self.progress_history.append({"time": current_time, "progress": value})
108
-
109
- # Keep only recent history (last 10 updates)
110
- if len(self.progress_history) > 10:
111
- self.progress_history = self.progress_history[-10:]
112
-
113
- def _calculate_eta(self, current_progress: float, current_time: float) -> str:
114
- """
115
- Calculate estimated time of arrival based on progress history.
116
-
117
- WHY: Uses historical data points to calculate a more accurate ETA
118
- than simple linear extrapolation, accounting for variations in
119
- processing speed.
120
- """
121
- if current_progress <= 0 or current_progress >= self.total:
122
- return ""
123
-
124
- # Need at least 2 data points for calculation
125
- if len(self.progress_history) < 2:
126
- return "Calculating ETA..."
127
-
128
- # Calculate average rate from recent history
129
- recent_history = self.progress_history[-5:] # Last 5 updates
130
- if len(recent_history) < 2:
131
- return "Calculating ETA..."
132
-
133
- time_span = recent_history[-1]["time"] - recent_history[0]["time"]
134
- progress_span = recent_history[-1]["progress"] - recent_history[0]["progress"]
135
-
136
- if time_span <= 0 or progress_span <= 0:
137
- return "Calculating ETA..."
138
-
139
- # Calculate rate (progress per second)
140
- rate = progress_span / time_span
141
-
142
- # Calculate remaining work and time
143
- remaining_progress = self.total - current_progress
144
- estimated_seconds = remaining_progress / rate
145
-
146
- # Format ETA
147
- if estimated_seconds < 60:
148
- return f"ETA: {estimated_seconds:.0f}s"
149
- elif estimated_seconds < 3600:
150
- minutes = estimated_seconds / 60
151
- return f"ETA: {minutes:.1f}m"
152
- else:
153
- hours = estimated_seconds / 3600
154
- return f"ETA: {hours:.1f}h"
155
-
156
- def reset(self) -> None:
157
- """Reset the progress widget to initial state."""
158
- self.progress = 0.0
159
- self.status_text = "Initializing..."
160
- self.start_time = time.time()
161
- self.progress_history = []
162
-
163
- # Reset UI elements
164
- progress_bar = self.query_one("#progress-bar", ProgressBar)
165
- progress_bar.update(progress=0)
166
-
167
- status_label = self.query_one("#status-label", Label)
168
- status_label.update("Initializing...")
169
-
170
- eta_label = self.query_one("#eta-label", Label)
171
- eta_label.update("")
172
-
173
- def complete(self, final_message: str = "Complete!") -> None:
174
- """Mark progress as complete."""
175
- self.update_progress(self.total, final_message)
176
-
177
- # Calculate total elapsed time
178
- total_time = time.time() - self.start_time
179
- if total_time < 60:
180
- time_str = f"{total_time:.1f}s"
181
- elif total_time < 3600:
182
- time_str = f"{total_time/60:.1f}m"
183
- else:
184
- time_str = f"{total_time/3600:.1f}h"
185
-
186
- eta_label = self.query_one("#eta-label", Label)
187
- eta_label.update(f"Completed in {time_str}")