gitflow-analytics 1.0.3__py3-none-any.whl → 1.3.11__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 (116) hide show
  1. gitflow_analytics/_version.py +1 -1
  2. gitflow_analytics/classification/__init__.py +31 -0
  3. gitflow_analytics/classification/batch_classifier.py +752 -0
  4. gitflow_analytics/classification/classifier.py +464 -0
  5. gitflow_analytics/classification/feature_extractor.py +725 -0
  6. gitflow_analytics/classification/linguist_analyzer.py +574 -0
  7. gitflow_analytics/classification/model.py +455 -0
  8. gitflow_analytics/cli.py +4158 -350
  9. gitflow_analytics/cli_rich.py +198 -48
  10. gitflow_analytics/config/__init__.py +43 -0
  11. gitflow_analytics/config/errors.py +261 -0
  12. gitflow_analytics/config/loader.py +905 -0
  13. gitflow_analytics/config/profiles.py +264 -0
  14. gitflow_analytics/config/repository.py +124 -0
  15. gitflow_analytics/config/schema.py +444 -0
  16. gitflow_analytics/config/validator.py +154 -0
  17. gitflow_analytics/config.py +44 -508
  18. gitflow_analytics/core/analyzer.py +1209 -98
  19. gitflow_analytics/core/cache.py +1337 -29
  20. gitflow_analytics/core/data_fetcher.py +1285 -0
  21. gitflow_analytics/core/identity.py +363 -14
  22. gitflow_analytics/core/metrics_storage.py +526 -0
  23. gitflow_analytics/core/progress.py +372 -0
  24. gitflow_analytics/core/schema_version.py +269 -0
  25. gitflow_analytics/extractors/ml_tickets.py +1100 -0
  26. gitflow_analytics/extractors/story_points.py +8 -1
  27. gitflow_analytics/extractors/tickets.py +749 -11
  28. gitflow_analytics/identity_llm/__init__.py +6 -0
  29. gitflow_analytics/identity_llm/analysis_pass.py +231 -0
  30. gitflow_analytics/identity_llm/analyzer.py +464 -0
  31. gitflow_analytics/identity_llm/models.py +76 -0
  32. gitflow_analytics/integrations/github_integration.py +175 -11
  33. gitflow_analytics/integrations/jira_integration.py +461 -24
  34. gitflow_analytics/integrations/orchestrator.py +124 -1
  35. gitflow_analytics/metrics/activity_scoring.py +322 -0
  36. gitflow_analytics/metrics/branch_health.py +470 -0
  37. gitflow_analytics/metrics/dora.py +379 -20
  38. gitflow_analytics/models/database.py +843 -53
  39. gitflow_analytics/pm_framework/__init__.py +115 -0
  40. gitflow_analytics/pm_framework/adapters/__init__.py +50 -0
  41. gitflow_analytics/pm_framework/adapters/jira_adapter.py +1845 -0
  42. gitflow_analytics/pm_framework/base.py +406 -0
  43. gitflow_analytics/pm_framework/models.py +211 -0
  44. gitflow_analytics/pm_framework/orchestrator.py +652 -0
  45. gitflow_analytics/pm_framework/registry.py +333 -0
  46. gitflow_analytics/qualitative/__init__.py +9 -10
  47. gitflow_analytics/qualitative/chatgpt_analyzer.py +259 -0
  48. gitflow_analytics/qualitative/classifiers/__init__.py +3 -3
  49. gitflow_analytics/qualitative/classifiers/change_type.py +518 -244
  50. gitflow_analytics/qualitative/classifiers/domain_classifier.py +272 -165
  51. gitflow_analytics/qualitative/classifiers/intent_analyzer.py +321 -222
  52. gitflow_analytics/qualitative/classifiers/llm/__init__.py +35 -0
  53. gitflow_analytics/qualitative/classifiers/llm/base.py +193 -0
  54. gitflow_analytics/qualitative/classifiers/llm/batch_processor.py +383 -0
  55. gitflow_analytics/qualitative/classifiers/llm/cache.py +479 -0
  56. gitflow_analytics/qualitative/classifiers/llm/cost_tracker.py +435 -0
  57. gitflow_analytics/qualitative/classifiers/llm/openai_client.py +403 -0
  58. gitflow_analytics/qualitative/classifiers/llm/prompts.py +373 -0
  59. gitflow_analytics/qualitative/classifiers/llm/response_parser.py +287 -0
  60. gitflow_analytics/qualitative/classifiers/llm_commit_classifier.py +607 -0
  61. gitflow_analytics/qualitative/classifiers/risk_analyzer.py +215 -189
  62. gitflow_analytics/qualitative/core/__init__.py +4 -4
  63. gitflow_analytics/qualitative/core/llm_fallback.py +239 -235
  64. gitflow_analytics/qualitative/core/nlp_engine.py +157 -148
  65. gitflow_analytics/qualitative/core/pattern_cache.py +214 -192
  66. gitflow_analytics/qualitative/core/processor.py +381 -248
  67. gitflow_analytics/qualitative/enhanced_analyzer.py +2236 -0
  68. gitflow_analytics/qualitative/example_enhanced_usage.py +420 -0
  69. gitflow_analytics/qualitative/models/__init__.py +7 -7
  70. gitflow_analytics/qualitative/models/schemas.py +155 -121
  71. gitflow_analytics/qualitative/utils/__init__.py +4 -4
  72. gitflow_analytics/qualitative/utils/batch_processor.py +136 -123
  73. gitflow_analytics/qualitative/utils/cost_tracker.py +142 -140
  74. gitflow_analytics/qualitative/utils/metrics.py +172 -158
  75. gitflow_analytics/qualitative/utils/text_processing.py +146 -104
  76. gitflow_analytics/reports/__init__.py +100 -0
  77. gitflow_analytics/reports/analytics_writer.py +539 -14
  78. gitflow_analytics/reports/base.py +648 -0
  79. gitflow_analytics/reports/branch_health_writer.py +322 -0
  80. gitflow_analytics/reports/classification_writer.py +924 -0
  81. gitflow_analytics/reports/cli_integration.py +427 -0
  82. gitflow_analytics/reports/csv_writer.py +1676 -212
  83. gitflow_analytics/reports/data_models.py +504 -0
  84. gitflow_analytics/reports/database_report_generator.py +427 -0
  85. gitflow_analytics/reports/example_usage.py +344 -0
  86. gitflow_analytics/reports/factory.py +499 -0
  87. gitflow_analytics/reports/formatters.py +698 -0
  88. gitflow_analytics/reports/html_generator.py +1116 -0
  89. gitflow_analytics/reports/interfaces.py +489 -0
  90. gitflow_analytics/reports/json_exporter.py +2770 -0
  91. gitflow_analytics/reports/narrative_writer.py +2287 -158
  92. gitflow_analytics/reports/story_point_correlation.py +1144 -0
  93. gitflow_analytics/reports/weekly_trends_writer.py +389 -0
  94. gitflow_analytics/training/__init__.py +5 -0
  95. gitflow_analytics/training/model_loader.py +377 -0
  96. gitflow_analytics/training/pipeline.py +550 -0
  97. gitflow_analytics/tui/__init__.py +1 -1
  98. gitflow_analytics/tui/app.py +129 -126
  99. gitflow_analytics/tui/screens/__init__.py +3 -3
  100. gitflow_analytics/tui/screens/analysis_progress_screen.py +188 -179
  101. gitflow_analytics/tui/screens/configuration_screen.py +154 -178
  102. gitflow_analytics/tui/screens/loading_screen.py +100 -110
  103. gitflow_analytics/tui/screens/main_screen.py +89 -72
  104. gitflow_analytics/tui/screens/results_screen.py +305 -281
  105. gitflow_analytics/tui/widgets/__init__.py +2 -2
  106. gitflow_analytics/tui/widgets/data_table.py +67 -69
  107. gitflow_analytics/tui/widgets/export_modal.py +76 -76
  108. gitflow_analytics/tui/widgets/progress_widget.py +41 -46
  109. gitflow_analytics-1.3.11.dist-info/METADATA +1015 -0
  110. gitflow_analytics-1.3.11.dist-info/RECORD +122 -0
  111. gitflow_analytics-1.0.3.dist-info/METADATA +0 -490
  112. gitflow_analytics-1.0.3.dist-info/RECORD +0 -62
  113. {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.11.dist-info}/WHEEL +0 -0
  114. {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.11.dist-info}/entry_points.txt +0 -0
  115. {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.11.dist-info}/licenses/LICENSE +0 -0
  116. {gitflow_analytics-1.0.3.dist-info → gitflow_analytics-1.3.11.dist-info}/top_level.txt +0 -0
@@ -2,27 +2,25 @@
2
2
 
3
3
  import time
4
4
  from typing import Optional
5
- from datetime import datetime, timedelta
6
5
 
7
- from textual.widgets import ProgressBar, Label
8
- from textual.containers import Container, Vertical
6
+ from textual.containers import Container
9
7
  from textual.reactive import reactive
10
- from rich.text import Text
8
+ from textual.widgets import Label, ProgressBar
11
9
 
12
10
 
13
11
  class AnalysisProgressWidget(Container):
14
12
  """
15
13
  Custom progress widget that shows progress with ETA calculation.
16
-
17
- WHY: Standard progress bars don't provide time estimates which are crucial
14
+
15
+ WHY: Standard progress bars don't provide time estimates which are crucial
18
16
  for long-running analysis operations. This widget combines progress tracking
19
17
  with ETA calculations to give users better feedback.
20
-
21
- DESIGN DECISION: Uses reactive attributes for real-time updates and
18
+
19
+ DESIGN DECISION: Uses reactive attributes for real-time updates and
22
20
  calculates ETA based on average processing speed rather than simple linear
23
21
  extrapolation for more accurate estimates.
24
22
  """
25
-
23
+
26
24
  DEFAULT_CSS = """
27
25
  AnalysisProgressWidget {
28
26
  height: auto;
@@ -47,11 +45,11 @@ class AnalysisProgressWidget(Container):
47
45
  text-style: italic;
48
46
  }
49
47
  """
50
-
48
+
51
49
  progress = reactive(0.0)
52
50
  total = reactive(100.0)
53
51
  status_text = reactive("Initializing...")
54
-
52
+
55
53
  def __init__(
56
54
  self,
57
55
  title: str,
@@ -59,7 +57,7 @@ class AnalysisProgressWidget(Container):
59
57
  *,
60
58
  name: Optional[str] = None,
61
59
  id: Optional[str] = None,
62
- classes: Optional[str] = None
60
+ classes: Optional[str] = None,
63
61
  ) -> None:
64
62
  super().__init__(name=name, id=id, classes=classes)
65
63
  self.title = title
@@ -67,87 +65,84 @@ class AnalysisProgressWidget(Container):
67
65
  self.start_time = time.time()
68
66
  self.last_update_time = time.time()
69
67
  self.progress_history = []
70
-
68
+
71
69
  def compose(self):
72
70
  """Compose the progress widget."""
73
71
  yield Label(self.title, classes="progress-title")
74
72
  yield ProgressBar(total=self.total, id="progress-bar")
75
73
  yield Label(self.status_text, classes="progress-status", id="status-label")
76
74
  yield Label("", classes="progress-eta", id="eta-label")
77
-
75
+
78
76
  def update_progress(self, value: float, status: str = "") -> None:
79
77
  """
80
78
  Update progress and status with ETA calculation.
81
-
79
+
82
80
  WHY: Provides comprehensive progress updates including time estimates
83
81
  which are essential for user experience during long operations.
84
-
82
+
85
83
  @param value: Current progress value
86
84
  @param status: Status message to display
87
85
  """
88
86
  current_time = time.time()
89
-
87
+
90
88
  # Update reactive values
91
89
  self.progress = value
92
90
  if status:
93
91
  self.status_text = status
94
-
92
+
95
93
  # Update progress bar
96
94
  progress_bar = self.query_one("#progress-bar", ProgressBar)
97
95
  progress_bar.update(progress=value)
98
-
96
+
99
97
  # Update status label
100
98
  status_label = self.query_one("#status-label", Label)
101
99
  status_label.update(status)
102
-
100
+
103
101
  # Calculate and update ETA
104
102
  eta_text = self._calculate_eta(value, current_time)
105
103
  eta_label = self.query_one("#eta-label", Label)
106
104
  eta_label.update(eta_text)
107
-
105
+
108
106
  # Store progress history for better ETA calculation
109
- self.progress_history.append({
110
- 'time': current_time,
111
- 'progress': value
112
- })
113
-
107
+ self.progress_history.append({"time": current_time, "progress": value})
108
+
114
109
  # Keep only recent history (last 10 updates)
115
110
  if len(self.progress_history) > 10:
116
111
  self.progress_history = self.progress_history[-10:]
117
-
112
+
118
113
  def _calculate_eta(self, current_progress: float, current_time: float) -> str:
119
114
  """
120
115
  Calculate estimated time of arrival based on progress history.
121
-
116
+
122
117
  WHY: Uses historical data points to calculate a more accurate ETA
123
- than simple linear extrapolation, accounting for variations in
118
+ than simple linear extrapolation, accounting for variations in
124
119
  processing speed.
125
120
  """
126
121
  if current_progress <= 0 or current_progress >= self.total:
127
122
  return ""
128
-
123
+
129
124
  # Need at least 2 data points for calculation
130
125
  if len(self.progress_history) < 2:
131
126
  return "Calculating ETA..."
132
-
127
+
133
128
  # Calculate average rate from recent history
134
129
  recent_history = self.progress_history[-5:] # Last 5 updates
135
130
  if len(recent_history) < 2:
136
131
  return "Calculating ETA..."
137
-
138
- time_span = recent_history[-1]['time'] - recent_history[0]['time']
139
- progress_span = recent_history[-1]['progress'] - recent_history[0]['progress']
140
-
132
+
133
+ time_span = recent_history[-1]["time"] - recent_history[0]["time"]
134
+ progress_span = recent_history[-1]["progress"] - recent_history[0]["progress"]
135
+
141
136
  if time_span <= 0 or progress_span <= 0:
142
137
  return "Calculating ETA..."
143
-
138
+
144
139
  # Calculate rate (progress per second)
145
140
  rate = progress_span / time_span
146
-
141
+
147
142
  # Calculate remaining work and time
148
143
  remaining_progress = self.total - current_progress
149
144
  estimated_seconds = remaining_progress / rate
150
-
145
+
151
146
  # Format ETA
152
147
  if estimated_seconds < 60:
153
148
  return f"ETA: {estimated_seconds:.0f}s"
@@ -157,28 +152,28 @@ class AnalysisProgressWidget(Container):
157
152
  else:
158
153
  hours = estimated_seconds / 3600
159
154
  return f"ETA: {hours:.1f}h"
160
-
155
+
161
156
  def reset(self) -> None:
162
157
  """Reset the progress widget to initial state."""
163
158
  self.progress = 0.0
164
159
  self.status_text = "Initializing..."
165
160
  self.start_time = time.time()
166
161
  self.progress_history = []
167
-
162
+
168
163
  # Reset UI elements
169
164
  progress_bar = self.query_one("#progress-bar", ProgressBar)
170
165
  progress_bar.update(progress=0)
171
-
166
+
172
167
  status_label = self.query_one("#status-label", Label)
173
168
  status_label.update("Initializing...")
174
-
169
+
175
170
  eta_label = self.query_one("#eta-label", Label)
176
171
  eta_label.update("")
177
-
172
+
178
173
  def complete(self, final_message: str = "Complete!") -> None:
179
174
  """Mark progress as complete."""
180
175
  self.update_progress(self.total, final_message)
181
-
176
+
182
177
  # Calculate total elapsed time
183
178
  total_time = time.time() - self.start_time
184
179
  if total_time < 60:
@@ -187,6 +182,6 @@ class AnalysisProgressWidget(Container):
187
182
  time_str = f"{total_time/60:.1f}m"
188
183
  else:
189
184
  time_str = f"{total_time/3600:.1f}h"
190
-
185
+
191
186
  eta_label = self.query_one("#eta-label", Label)
192
- eta_label.update(f"Completed in {time_str}")
187
+ eta_label.update(f"Completed in {time_str}")