gitflow-analytics 1.0.1__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.
Files changed (119) hide show
  1. gitflow_analytics/__init__.py +11 -11
  2. gitflow_analytics/_version.py +2 -2
  3. gitflow_analytics/classification/__init__.py +31 -0
  4. gitflow_analytics/classification/batch_classifier.py +752 -0
  5. gitflow_analytics/classification/classifier.py +464 -0
  6. gitflow_analytics/classification/feature_extractor.py +725 -0
  7. gitflow_analytics/classification/linguist_analyzer.py +574 -0
  8. gitflow_analytics/classification/model.py +455 -0
  9. gitflow_analytics/cli.py +4490 -378
  10. gitflow_analytics/cli_rich.py +503 -0
  11. gitflow_analytics/config/__init__.py +43 -0
  12. gitflow_analytics/config/errors.py +261 -0
  13. gitflow_analytics/config/loader.py +904 -0
  14. gitflow_analytics/config/profiles.py +264 -0
  15. gitflow_analytics/config/repository.py +124 -0
  16. gitflow_analytics/config/schema.py +441 -0
  17. gitflow_analytics/config/validator.py +154 -0
  18. gitflow_analytics/config.py +44 -398
  19. gitflow_analytics/core/analyzer.py +1320 -172
  20. gitflow_analytics/core/branch_mapper.py +132 -132
  21. gitflow_analytics/core/cache.py +1554 -175
  22. gitflow_analytics/core/data_fetcher.py +1193 -0
  23. gitflow_analytics/core/identity.py +571 -185
  24. gitflow_analytics/core/metrics_storage.py +526 -0
  25. gitflow_analytics/core/progress.py +372 -0
  26. gitflow_analytics/core/schema_version.py +269 -0
  27. gitflow_analytics/extractors/base.py +13 -11
  28. gitflow_analytics/extractors/ml_tickets.py +1100 -0
  29. gitflow_analytics/extractors/story_points.py +77 -59
  30. gitflow_analytics/extractors/tickets.py +841 -89
  31. gitflow_analytics/identity_llm/__init__.py +6 -0
  32. gitflow_analytics/identity_llm/analysis_pass.py +231 -0
  33. gitflow_analytics/identity_llm/analyzer.py +464 -0
  34. gitflow_analytics/identity_llm/models.py +76 -0
  35. gitflow_analytics/integrations/github_integration.py +258 -87
  36. gitflow_analytics/integrations/jira_integration.py +572 -123
  37. gitflow_analytics/integrations/orchestrator.py +206 -82
  38. gitflow_analytics/metrics/activity_scoring.py +322 -0
  39. gitflow_analytics/metrics/branch_health.py +470 -0
  40. gitflow_analytics/metrics/dora.py +542 -179
  41. gitflow_analytics/models/database.py +986 -59
  42. gitflow_analytics/pm_framework/__init__.py +115 -0
  43. gitflow_analytics/pm_framework/adapters/__init__.py +50 -0
  44. gitflow_analytics/pm_framework/adapters/jira_adapter.py +1845 -0
  45. gitflow_analytics/pm_framework/base.py +406 -0
  46. gitflow_analytics/pm_framework/models.py +211 -0
  47. gitflow_analytics/pm_framework/orchestrator.py +652 -0
  48. gitflow_analytics/pm_framework/registry.py +333 -0
  49. gitflow_analytics/qualitative/__init__.py +29 -0
  50. gitflow_analytics/qualitative/chatgpt_analyzer.py +259 -0
  51. gitflow_analytics/qualitative/classifiers/__init__.py +13 -0
  52. gitflow_analytics/qualitative/classifiers/change_type.py +742 -0
  53. gitflow_analytics/qualitative/classifiers/domain_classifier.py +506 -0
  54. gitflow_analytics/qualitative/classifiers/intent_analyzer.py +535 -0
  55. gitflow_analytics/qualitative/classifiers/llm/__init__.py +35 -0
  56. gitflow_analytics/qualitative/classifiers/llm/base.py +193 -0
  57. gitflow_analytics/qualitative/classifiers/llm/batch_processor.py +383 -0
  58. gitflow_analytics/qualitative/classifiers/llm/cache.py +479 -0
  59. gitflow_analytics/qualitative/classifiers/llm/cost_tracker.py +435 -0
  60. gitflow_analytics/qualitative/classifiers/llm/openai_client.py +403 -0
  61. gitflow_analytics/qualitative/classifiers/llm/prompts.py +373 -0
  62. gitflow_analytics/qualitative/classifiers/llm/response_parser.py +287 -0
  63. gitflow_analytics/qualitative/classifiers/llm_commit_classifier.py +607 -0
  64. gitflow_analytics/qualitative/classifiers/risk_analyzer.py +438 -0
  65. gitflow_analytics/qualitative/core/__init__.py +13 -0
  66. gitflow_analytics/qualitative/core/llm_fallback.py +657 -0
  67. gitflow_analytics/qualitative/core/nlp_engine.py +382 -0
  68. gitflow_analytics/qualitative/core/pattern_cache.py +479 -0
  69. gitflow_analytics/qualitative/core/processor.py +673 -0
  70. gitflow_analytics/qualitative/enhanced_analyzer.py +2236 -0
  71. gitflow_analytics/qualitative/example_enhanced_usage.py +420 -0
  72. gitflow_analytics/qualitative/models/__init__.py +25 -0
  73. gitflow_analytics/qualitative/models/schemas.py +306 -0
  74. gitflow_analytics/qualitative/utils/__init__.py +13 -0
  75. gitflow_analytics/qualitative/utils/batch_processor.py +339 -0
  76. gitflow_analytics/qualitative/utils/cost_tracker.py +345 -0
  77. gitflow_analytics/qualitative/utils/metrics.py +361 -0
  78. gitflow_analytics/qualitative/utils/text_processing.py +285 -0
  79. gitflow_analytics/reports/__init__.py +100 -0
  80. gitflow_analytics/reports/analytics_writer.py +550 -18
  81. gitflow_analytics/reports/base.py +648 -0
  82. gitflow_analytics/reports/branch_health_writer.py +322 -0
  83. gitflow_analytics/reports/classification_writer.py +924 -0
  84. gitflow_analytics/reports/cli_integration.py +427 -0
  85. gitflow_analytics/reports/csv_writer.py +1700 -216
  86. gitflow_analytics/reports/data_models.py +504 -0
  87. gitflow_analytics/reports/database_report_generator.py +427 -0
  88. gitflow_analytics/reports/example_usage.py +344 -0
  89. gitflow_analytics/reports/factory.py +499 -0
  90. gitflow_analytics/reports/formatters.py +698 -0
  91. gitflow_analytics/reports/html_generator.py +1116 -0
  92. gitflow_analytics/reports/interfaces.py +489 -0
  93. gitflow_analytics/reports/json_exporter.py +2770 -0
  94. gitflow_analytics/reports/narrative_writer.py +2289 -158
  95. gitflow_analytics/reports/story_point_correlation.py +1144 -0
  96. gitflow_analytics/reports/weekly_trends_writer.py +389 -0
  97. gitflow_analytics/training/__init__.py +5 -0
  98. gitflow_analytics/training/model_loader.py +377 -0
  99. gitflow_analytics/training/pipeline.py +550 -0
  100. gitflow_analytics/tui/__init__.py +5 -0
  101. gitflow_analytics/tui/app.py +724 -0
  102. gitflow_analytics/tui/screens/__init__.py +8 -0
  103. gitflow_analytics/tui/screens/analysis_progress_screen.py +496 -0
  104. gitflow_analytics/tui/screens/configuration_screen.py +523 -0
  105. gitflow_analytics/tui/screens/loading_screen.py +348 -0
  106. gitflow_analytics/tui/screens/main_screen.py +321 -0
  107. gitflow_analytics/tui/screens/results_screen.py +722 -0
  108. gitflow_analytics/tui/widgets/__init__.py +7 -0
  109. gitflow_analytics/tui/widgets/data_table.py +255 -0
  110. gitflow_analytics/tui/widgets/export_modal.py +301 -0
  111. gitflow_analytics/tui/widgets/progress_widget.py +187 -0
  112. gitflow_analytics-1.3.6.dist-info/METADATA +1015 -0
  113. gitflow_analytics-1.3.6.dist-info/RECORD +122 -0
  114. gitflow_analytics-1.0.1.dist-info/METADATA +0 -463
  115. gitflow_analytics-1.0.1.dist-info/RECORD +0 -31
  116. {gitflow_analytics-1.0.1.dist-info → gitflow_analytics-1.3.6.dist-info}/WHEEL +0 -0
  117. {gitflow_analytics-1.0.1.dist-info → gitflow_analytics-1.3.6.dist-info}/entry_points.txt +0 -0
  118. {gitflow_analytics-1.0.1.dist-info → gitflow_analytics-1.3.6.dist-info}/licenses/LICENSE +0 -0
  119. {gitflow_analytics-1.0.1.dist-info → gitflow_analytics-1.3.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,261 @@
1
+ """Configuration error handling and user-friendly error messages."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Optional
5
+
6
+ import yaml
7
+
8
+
9
+ class ConfigurationError(ValueError):
10
+ """Base exception for configuration-related errors."""
11
+
12
+ def __init__(
13
+ self, message: str, config_path: Optional[Path] = None, suggestion: Optional[str] = None
14
+ ):
15
+ """Initialize configuration error.
16
+
17
+ Args:
18
+ message: The error message
19
+ config_path: Path to the configuration file
20
+ suggestion: Helpful suggestion for fixing the error
21
+ """
22
+ self.message = message
23
+ self.config_path = config_path
24
+ self.suggestion = suggestion
25
+ super().__init__(self._format_message())
26
+
27
+ def _format_message(self) -> str:
28
+ """Format the error message with context and suggestions."""
29
+ msg = f"❌ {self.message}"
30
+ if self.suggestion:
31
+ msg += f"\n\n💡 {self.suggestion}"
32
+ if self.config_path:
33
+ msg += f"\n\n📁 File: {self.config_path}"
34
+ return msg
35
+
36
+
37
+ class YAMLParseError(ConfigurationError):
38
+ """YAML parsing error with user-friendly messages."""
39
+
40
+ @classmethod
41
+ def from_yaml_error(cls, error: yaml.YAMLError, config_path: Path) -> "YAMLParseError":
42
+ """Create YAMLParseError from yaml.YAMLError with helpful guidance.
43
+
44
+ Args:
45
+ error: The original YAML error
46
+ config_path: Path to the configuration file
47
+
48
+ Returns:
49
+ YAMLParseError with user-friendly message
50
+ """
51
+ file_name = config_path.name
52
+
53
+ # Extract error details if available
54
+ line_number = getattr(error, "problem_mark", None)
55
+ context_mark = getattr(error, "context_mark", None)
56
+ problem = getattr(error, "problem", str(error))
57
+ context = getattr(error, "context", None)
58
+
59
+ # Build error message parts
60
+ location_info = ""
61
+ if line_number:
62
+ location_info = f" at line {line_number.line + 1}, column {line_number.column + 1}"
63
+ elif context_mark:
64
+ location_info = f" at line {context_mark.line + 1}, column {context_mark.column + 1}"
65
+
66
+ # Create user-friendly error message
67
+ base_msg = f"YAML configuration error in {file_name}{location_info}"
68
+
69
+ # Detect common YAML issues and provide specific guidance
70
+ problem_lower = problem.lower()
71
+ suggestion = cls._get_suggestion_for_problem(problem_lower, context)
72
+
73
+ # Add context information if available
74
+ if context and context != problem:
75
+ base_msg += f"\n📍 Context: {context}"
76
+
77
+ # Add helpful resources
78
+ base_msg += "\n\n🔗 For YAML syntax help, visit: https://yaml.org/spec/1.2/spec.html"
79
+ base_msg += "\n Or use an online YAML validator to check your syntax."
80
+
81
+ return cls(base_msg, config_path, suggestion)
82
+
83
+ @staticmethod
84
+ def _get_suggestion_for_problem(problem_lower: str, context: Optional[str] = None) -> str:
85
+ """Get specific suggestion based on the YAML problem.
86
+
87
+ Args:
88
+ problem_lower: Lowercase problem description
89
+ context: Optional context string
90
+
91
+ Returns:
92
+ Helpful suggestion for fixing the problem
93
+ """
94
+ if "found character '\\t'" in problem_lower.replace("'", "'"):
95
+ return (
96
+ "🚫 Tab characters are not allowed in YAML files!\n\n"
97
+ "Fix: Replace all tab characters with spaces (usually 2 or 4 spaces).\n"
98
+ " Most editors can show whitespace characters and convert tabs to spaces.\n"
99
+ " In VS Code: View → Render Whitespace, then Edit → Convert Indentation to Spaces"
100
+ )
101
+
102
+ elif "mapping values are not allowed here" in problem_lower:
103
+ return (
104
+ "🚫 Invalid YAML syntax - missing colon or incorrect indentation!\n\n"
105
+ "Common fixes:\n"
106
+ " • Add a colon (:) after the key name\n"
107
+ " • Check that all lines are properly indented with spaces\n"
108
+ " • Ensure nested items are indented consistently"
109
+ )
110
+
111
+ elif "could not find expected" in problem_lower and ":" in problem_lower:
112
+ return (
113
+ "🚫 Missing colon (:) after a key name!\n\n"
114
+ "Fix: Add a colon and space after the key name.\n"
115
+ " Example: 'key_name: value' not 'key_name value'"
116
+ )
117
+
118
+ elif "found undefined alias" in problem_lower:
119
+ return (
120
+ "🚫 YAML alias reference not found!\n\n"
121
+ "Fix: Check that the referenced alias (&name) is defined before using it (*name)"
122
+ )
123
+
124
+ elif "expected <block end>" in problem_lower:
125
+ return (
126
+ "🚫 Incorrect indentation or missing content!\n\n"
127
+ "Common fixes:\n"
128
+ " • Check that all nested items are properly indented\n"
129
+ " • Ensure list items start with '- ' (dash and space)\n"
130
+ " • Make sure there's content after colons"
131
+ )
132
+
133
+ elif "while scanning a quoted scalar" in problem_lower:
134
+ return (
135
+ "🚫 Unclosed or incorrectly quoted string!\n\n"
136
+ "Fix: Check that all quotes are properly closed.\n"
137
+ " • Use matching quotes: 'text' or \"text\"\n"
138
+ ' • Escape quotes inside strings: \'don\\\'t\' or "say \\"hello\\""'
139
+ )
140
+
141
+ elif "found unexpected end of stream" in problem_lower:
142
+ return (
143
+ "🚫 Incomplete YAML structure!\n\n"
144
+ "Fix: The file appears to end unexpectedly.\n"
145
+ " • Check that all sections are complete\n"
146
+ " • Ensure there are no missing closing brackets or braces"
147
+ )
148
+
149
+ elif "found unknown escape character" in problem_lower:
150
+ return (
151
+ "🚫 Invalid escape sequence in quoted string!\n\n"
152
+ "Fix: Use proper YAML escape sequences or raw strings.\n"
153
+ ' • For regex patterns: Use double quotes and double backslashes ("\\\\d+")\n'
154
+ " • For file paths: Use forward slashes or double backslashes\n"
155
+ " • Or use single quotes for literal strings: 'C:\\path\\to\\file'"
156
+ )
157
+
158
+ elif "scanner" in problem_lower and "character" in problem_lower:
159
+ return (
160
+ "🚫 Invalid character in YAML file!\n\n"
161
+ "Fix: Check for special characters that need to be quoted.\n"
162
+ " • Wrap values containing special characters in quotes\n"
163
+ " • Common problematic characters: @, `, |, >, [, ], {, }"
164
+ )
165
+
166
+ else:
167
+ return (
168
+ f"🚫 YAML parsing error: {problem_lower}\n\n"
169
+ "Common YAML issues to check:\n"
170
+ " • Use spaces for indentation, not tabs\n"
171
+ " • Add colons (:) after key names\n"
172
+ " • Ensure consistent indentation (usually 2 or 4 spaces)\n"
173
+ " • Quote strings containing special characters\n"
174
+ " • Use '- ' (dash and space) for list items"
175
+ )
176
+
177
+
178
+ class MissingFieldError(ConfigurationError):
179
+ """Error for missing required configuration fields."""
180
+
181
+ def __init__(
182
+ self,
183
+ field_name: str,
184
+ section: str,
185
+ config_path: Optional[Path] = None,
186
+ example: Optional[str] = None,
187
+ ):
188
+ """Initialize missing field error.
189
+
190
+ Args:
191
+ field_name: Name of the missing field
192
+ section: Configuration section containing the field
193
+ config_path: Path to the configuration file
194
+ example: Example of correct usage
195
+ """
196
+ message = f"Missing required field '{field_name}' in {section}"
197
+ suggestion = f"Add the '{field_name}' field to your configuration"
198
+ if example:
199
+ suggestion += f":\n {example}"
200
+ super().__init__(message, config_path, suggestion)
201
+
202
+
203
+ class InvalidValueError(ConfigurationError):
204
+ """Error for invalid configuration values."""
205
+
206
+ def __init__(
207
+ self,
208
+ field_name: str,
209
+ value: Any,
210
+ reason: str,
211
+ config_path: Optional[Path] = None,
212
+ valid_values: Optional[list] = None,
213
+ ):
214
+ """Initialize invalid value error.
215
+
216
+ Args:
217
+ field_name: Name of the field with invalid value
218
+ value: The invalid value
219
+ reason: Reason why the value is invalid
220
+ config_path: Path to the configuration file
221
+ valid_values: List of valid values (if applicable)
222
+ """
223
+ message = f"Invalid value for '{field_name}': {value} - {reason}"
224
+ suggestion = f"Check the value of '{field_name}'"
225
+ if valid_values:
226
+ suggestion += f"\n Valid values: {', '.join(str(v) for v in valid_values)}"
227
+ super().__init__(message, config_path, suggestion)
228
+
229
+
230
+ class EnvironmentVariableError(ConfigurationError):
231
+ """Error for missing environment variables."""
232
+
233
+ def __init__(self, var_name: str, field_context: str, config_path: Optional[Path] = None):
234
+ """Initialize environment variable error.
235
+
236
+ Args:
237
+ var_name: Name of the missing environment variable
238
+ field_context: Context where the variable is used
239
+ config_path: Path to the configuration file
240
+ """
241
+ message = f"{field_context} is configured but {var_name} environment variable is not set"
242
+ suggestion = (
243
+ f"Set the {var_name} environment variable:\n"
244
+ f" • Export directly: export {var_name}='your_value'\n"
245
+ f" • Or create a .env file in the same directory as your config:\n"
246
+ f" {var_name}=your_value"
247
+ )
248
+ super().__init__(message, config_path, suggestion)
249
+
250
+
251
+ def handle_yaml_error(error: yaml.YAMLError, config_path: Path) -> None:
252
+ """Handle YAML parsing errors with user-friendly messages.
253
+
254
+ Args:
255
+ error: The YAML error to handle
256
+ config_path: Path to the configuration file
257
+
258
+ Raises:
259
+ YAMLParseError: With user-friendly error message
260
+ """
261
+ raise YAMLParseError.from_yaml_error(error, config_path)