gitflow-analytics 1.0.0__py3-none-any.whl → 1.0.3__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 (58) hide show
  1. gitflow_analytics/__init__.py +11 -9
  2. gitflow_analytics/_version.py +2 -2
  3. gitflow_analytics/cli.py +691 -243
  4. gitflow_analytics/cli_rich.py +353 -0
  5. gitflow_analytics/config.py +389 -96
  6. gitflow_analytics/core/analyzer.py +175 -78
  7. gitflow_analytics/core/branch_mapper.py +132 -132
  8. gitflow_analytics/core/cache.py +242 -173
  9. gitflow_analytics/core/identity.py +214 -178
  10. gitflow_analytics/extractors/base.py +13 -11
  11. gitflow_analytics/extractors/story_points.py +70 -59
  12. gitflow_analytics/extractors/tickets.py +111 -88
  13. gitflow_analytics/integrations/github_integration.py +91 -77
  14. gitflow_analytics/integrations/jira_integration.py +284 -0
  15. gitflow_analytics/integrations/orchestrator.py +99 -72
  16. gitflow_analytics/metrics/dora.py +183 -179
  17. gitflow_analytics/models/database.py +191 -54
  18. gitflow_analytics/qualitative/__init__.py +30 -0
  19. gitflow_analytics/qualitative/classifiers/__init__.py +13 -0
  20. gitflow_analytics/qualitative/classifiers/change_type.py +468 -0
  21. gitflow_analytics/qualitative/classifiers/domain_classifier.py +399 -0
  22. gitflow_analytics/qualitative/classifiers/intent_analyzer.py +436 -0
  23. gitflow_analytics/qualitative/classifiers/risk_analyzer.py +412 -0
  24. gitflow_analytics/qualitative/core/__init__.py +13 -0
  25. gitflow_analytics/qualitative/core/llm_fallback.py +653 -0
  26. gitflow_analytics/qualitative/core/nlp_engine.py +373 -0
  27. gitflow_analytics/qualitative/core/pattern_cache.py +457 -0
  28. gitflow_analytics/qualitative/core/processor.py +540 -0
  29. gitflow_analytics/qualitative/models/__init__.py +25 -0
  30. gitflow_analytics/qualitative/models/schemas.py +272 -0
  31. gitflow_analytics/qualitative/utils/__init__.py +13 -0
  32. gitflow_analytics/qualitative/utils/batch_processor.py +326 -0
  33. gitflow_analytics/qualitative/utils/cost_tracker.py +343 -0
  34. gitflow_analytics/qualitative/utils/metrics.py +347 -0
  35. gitflow_analytics/qualitative/utils/text_processing.py +243 -0
  36. gitflow_analytics/reports/analytics_writer.py +25 -8
  37. gitflow_analytics/reports/csv_writer.py +60 -32
  38. gitflow_analytics/reports/narrative_writer.py +21 -15
  39. gitflow_analytics/tui/__init__.py +5 -0
  40. gitflow_analytics/tui/app.py +721 -0
  41. gitflow_analytics/tui/screens/__init__.py +8 -0
  42. gitflow_analytics/tui/screens/analysis_progress_screen.py +487 -0
  43. gitflow_analytics/tui/screens/configuration_screen.py +547 -0
  44. gitflow_analytics/tui/screens/loading_screen.py +358 -0
  45. gitflow_analytics/tui/screens/main_screen.py +304 -0
  46. gitflow_analytics/tui/screens/results_screen.py +698 -0
  47. gitflow_analytics/tui/widgets/__init__.py +7 -0
  48. gitflow_analytics/tui/widgets/data_table.py +257 -0
  49. gitflow_analytics/tui/widgets/export_modal.py +301 -0
  50. gitflow_analytics/tui/widgets/progress_widget.py +192 -0
  51. gitflow_analytics-1.0.3.dist-info/METADATA +490 -0
  52. gitflow_analytics-1.0.3.dist-info/RECORD +62 -0
  53. gitflow_analytics-1.0.0.dist-info/METADATA +0 -201
  54. gitflow_analytics-1.0.0.dist-info/RECORD +0 -30
  55. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/WHEEL +0 -0
  56. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/entry_points.txt +0 -0
  57. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/licenses/LICENSE +0 -0
  58. {gitflow_analytics-1.0.0.dist-info → gitflow_analytics-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,93 +1,120 @@
1
1
  """Integration orchestrator for multiple platforms."""
2
- from typing import Dict, Any, List, Optional
3
- from datetime import datetime
2
+
4
3
  import json
4
+ from datetime import datetime
5
+ from typing import Any, Union
5
6
 
6
7
  from ..core.cache import GitAnalysisCache
7
8
  from .github_integration import GitHubIntegration
9
+ from .jira_integration import JIRAIntegration
8
10
 
9
11
 
10
12
  class IntegrationOrchestrator:
11
13
  """Orchestrate integrations with multiple platforms."""
12
-
14
+
13
15
  def __init__(self, config: Any, cache: GitAnalysisCache):
14
16
  """Initialize integration orchestrator."""
15
17
  self.config = config
16
18
  self.cache = cache
17
- self.integrations = {}
18
-
19
+ self.integrations: dict[str, Union[GitHubIntegration, JIRAIntegration]] = {}
20
+
19
21
  # Initialize available integrations
20
22
  if config.github and config.github.token:
21
- self.integrations['github'] = GitHubIntegration(
23
+ self.integrations["github"] = GitHubIntegration(
22
24
  config.github.token,
23
25
  cache,
24
26
  config.github.max_retries,
25
- config.github.backoff_factor
27
+ config.github.backoff_factor,
28
+ allowed_ticket_platforms=getattr(config.analysis, "ticket_platforms", None),
26
29
  )
27
-
28
- def enrich_repository_data(self, repo_config: Any, commits: List[Dict[str, Any]],
29
- since: datetime) -> Dict[str, Any]:
30
+
31
+ # Initialize JIRA integration if configured
32
+ if config.jira and config.jira.access_user and config.jira.access_token:
33
+ # Get JIRA specific settings if available
34
+ jira_settings = getattr(config, "jira_integration", {})
35
+ if hasattr(jira_settings, "enabled") and jira_settings.enabled:
36
+ base_url = getattr(config.jira, "base_url", None)
37
+ if base_url:
38
+ self.integrations["jira"] = JIRAIntegration(
39
+ base_url,
40
+ config.jira.access_user,
41
+ config.jira.access_token,
42
+ cache,
43
+ story_point_fields=getattr(jira_settings, "story_point_fields", None),
44
+ )
45
+
46
+ def enrich_repository_data(
47
+ self, repo_config: Any, commits: list[dict[str, Any]], since: datetime
48
+ ) -> dict[str, Any]:
30
49
  """Enrich repository data from all available integrations."""
31
- enrichment = {
32
- 'prs': [],
33
- 'issues': [],
34
- 'pr_metrics': {}
35
- }
36
-
50
+ enrichment: dict[str, Any] = {"prs": [], "issues": [], "pr_metrics": {}}
51
+
37
52
  # GitHub enrichment
38
- if 'github' in self.integrations and repo_config.github_repo:
39
- github = self.integrations['github']
40
-
41
- try:
42
- # Get PR data
43
- prs = github.enrich_repository_with_prs(
44
- repo_config.github_repo, commits, since
45
- )
46
- enrichment['prs'] = prs
47
-
48
- # Calculate PR metrics
49
- if prs:
50
- enrichment['pr_metrics'] = github.calculate_pr_metrics(prs)
51
-
52
- except Exception as e:
53
- print(f" ⚠️ GitHub enrichment failed: {e}")
54
-
55
- # Future: Add other platform integrations here
56
- # - ClickUp
57
- # - JIRA
58
- # - Linear
59
-
53
+ if "github" in self.integrations and repo_config.github_repo:
54
+ github_integration = self.integrations["github"]
55
+ if isinstance(github_integration, GitHubIntegration):
56
+ try:
57
+ # Get PR data
58
+ prs = github_integration.enrich_repository_with_prs(
59
+ repo_config.github_repo, commits, since
60
+ )
61
+ enrichment["prs"] = prs
62
+
63
+ # Calculate PR metrics
64
+ if prs:
65
+ enrichment["pr_metrics"] = github_integration.calculate_pr_metrics(prs)
66
+
67
+ except Exception as e:
68
+ print(f" ⚠️ GitHub enrichment failed: {e}")
69
+
70
+ # JIRA enrichment for story points
71
+ if "jira" in self.integrations:
72
+ jira_integration = self.integrations["jira"]
73
+ if isinstance(jira_integration, JIRAIntegration):
74
+ try:
75
+ # Enrich commits with JIRA story points
76
+ jira_integration.enrich_commits_with_jira_data(commits)
77
+
78
+ # Enrich PRs with JIRA story points
79
+ if enrichment["prs"]:
80
+ jira_integration.enrich_prs_with_jira_data(enrichment["prs"])
81
+
82
+ except Exception as e:
83
+ print(f" ⚠️ JIRA enrichment failed: {e}")
84
+
60
85
  return enrichment
61
-
62
- def get_platform_issues(self, project_key: str, since: datetime) -> List[Dict[str, Any]]:
86
+
87
+ def get_platform_issues(self, project_key: str, since: datetime) -> list[dict[str, Any]]:
63
88
  """Get issues from all configured platforms."""
64
- all_issues = []
65
-
89
+ all_issues: list[dict[str, Any]] = []
90
+
66
91
  # Check cache first
67
92
  cached_issues = []
68
- for platform in ['github', 'jira', 'clickup', 'linear']:
93
+ for platform in ["github", "jira", "clickup", "linear"]:
69
94
  cached = self.cache.get_cached_issues(platform, project_key)
70
95
  cached_issues.extend(cached)
71
-
96
+
72
97
  if cached_issues:
73
98
  return cached_issues
74
-
99
+
75
100
  # Future: Fetch from APIs if not cached
76
101
  # This is where we'd add actual API calls to each platform
77
-
102
+
78
103
  return all_issues
79
-
80
- def export_to_json(self,
81
- commits: List[Dict[str, Any]],
82
- prs: List[Dict[str, Any]],
83
- developer_stats: List[Dict[str, Any]],
84
- project_metrics: Dict[str, Any],
85
- dora_metrics: Dict[str, Any],
86
- output_path: str) -> str:
104
+
105
+ def export_to_json(
106
+ self,
107
+ commits: list[dict[str, Any]],
108
+ prs: list[dict[str, Any]],
109
+ developer_stats: list[dict[str, Any]],
110
+ project_metrics: dict[str, Any],
111
+ dora_metrics: dict[str, Any],
112
+ output_path: str,
113
+ ) -> str:
87
114
  """Export all data to JSON format for API consumption."""
88
-
115
+
89
116
  # Prepare data for JSON serialization
90
- def serialize_dates(obj):
117
+ def serialize_dates(obj: Any) -> Any:
91
118
  """Convert datetime objects to ISO format strings."""
92
119
  if isinstance(obj, datetime):
93
120
  return obj.isoformat()
@@ -96,24 +123,24 @@ class IntegrationOrchestrator:
96
123
  elif isinstance(obj, list):
97
124
  return [serialize_dates(item) for item in obj]
98
125
  return obj
99
-
126
+
100
127
  export_data = {
101
- 'metadata': {
102
- 'generated_at': datetime.now().isoformat(),
103
- 'version': '1.0',
104
- 'total_commits': len(commits),
105
- 'total_prs': len(prs),
106
- 'total_developers': len(developer_stats)
128
+ "metadata": {
129
+ "generated_at": datetime.now().isoformat(),
130
+ "version": "1.0",
131
+ "total_commits": len(commits),
132
+ "total_prs": len(prs),
133
+ "total_developers": len(developer_stats),
107
134
  },
108
- 'commits': serialize_dates(commits),
109
- 'pull_requests': serialize_dates(prs),
110
- 'developers': serialize_dates(developer_stats),
111
- 'project_metrics': serialize_dates(project_metrics),
112
- 'dora_metrics': serialize_dates(dora_metrics)
135
+ "commits": serialize_dates(commits),
136
+ "pull_requests": serialize_dates(prs),
137
+ "developers": serialize_dates(developer_stats),
138
+ "project_metrics": serialize_dates(project_metrics),
139
+ "dora_metrics": serialize_dates(dora_metrics),
113
140
  }
114
-
141
+
115
142
  # Write JSON file
116
- with open(output_path, 'w') as f:
143
+ with open(output_path, "w") as f:
117
144
  json.dump(export_data, f, indent=2)
118
-
119
- return output_path
145
+
146
+ return output_path