greenmining 1.1.6__py3-none-any.whl → 1.1.7__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.
greenmining/__init__.py CHANGED
@@ -9,7 +9,7 @@ from greenmining.gsf_patterns import (
9
9
  is_green_aware,
10
10
  )
11
11
 
12
- __version__ = "1.1.6"
12
+ __version__ = "1.1.7"
13
13
 
14
14
 
15
15
  def fetch_repositories(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: greenmining
3
- Version: 1.1.6
3
+ Version: 1.1.7
4
4
  Summary: An empirical Python library for Mining Software Repositories (MSR) in Green IT research
5
5
  Author-email: Adam Bouafia <a.bouafia@student.vu.nl>
6
6
  License: MIT
@@ -49,8 +49,6 @@ Requires-Dist: twine; extra == "dev"
49
49
  Provides-Extra: energy
50
50
  Requires-Dist: psutil; extra == "energy"
51
51
  Requires-Dist: codecarbon; extra == "energy"
52
- Provides-Extra: dashboard
53
- Requires-Dist: flask; extra == "dashboard"
54
52
  Provides-Extra: docs
55
53
  Requires-Dist: sphinx; extra == "docs"
56
54
  Requires-Dist: sphinx-rtd-theme; extra == "docs"
@@ -80,7 +78,6 @@ An empirical Python library for Mining Software Repositories (MSR) in Green IT r
80
78
  - **Method-level analysis** - Per-method complexity and metrics via Lizard integration
81
79
  - **Version power comparison** - Compare power consumption across software versions
82
80
  - **Generate research datasets** - Statistical analysis, temporal trends, and publication-ready reports
83
- - **Web dashboard** - Flask-based interactive visualization of analysis results
84
81
 
85
82
  Whether you're conducting MSR research, analyzing green software adoption, or measuring the energy footprint of codebases, GreenMining provides the empirical toolkit you need.
86
83
 
@@ -452,15 +449,6 @@ print(f"Spearman: {correlator.spearman}")
452
449
  print(f"Feature importance: {correlator.feature_importance}")
453
450
  ```
454
451
 
455
- #### Web Dashboard
456
-
457
- ```python
458
- from greenmining.dashboard import run_dashboard
459
-
460
- # Launch interactive dashboard (requires pip install greenmining[dashboard])
461
- run_dashboard(data_dir="./data", host="127.0.0.1", port=5000)
462
- ```
463
-
464
452
  #### Pipeline Batch Analysis
465
453
 
466
454
  ```python
@@ -698,7 +686,6 @@ config = Config(
698
686
  - **Full Process Metrics**: All 8 process metrics (ChangeSet, CodeChurn, CommitsCount, ContributorsCount, ContributorsExperience, HistoryComplexity, HunksCount, LinesCount)
699
687
  - **Statistical Analysis**: Correlations, effect sizes, and temporal trends
700
688
  - **Multi-format Output**: Markdown reports, CSV exports, JSON data
701
- - **Web Dashboard**: Flask-based interactive visualization (`pip install greenmining[dashboard]`)
702
689
  - **Docker Support**: Pre-built images for containerized analysis
703
690
 
704
691
  ### Energy Measurement
@@ -857,7 +844,6 @@ ruff check greenmining/ tests/
857
844
 
858
845
  ```bash
859
846
  pip install greenmining[energy] # psutil, codecarbon (energy measurement)
860
- pip install greenmining[dashboard] # flask (web dashboard)
861
847
  pip install greenmining[dev] # pytest, black, ruff, mypy (development)
862
848
  ```
863
849
 
@@ -1,4 +1,4 @@
1
- greenmining/__init__.py,sha256=jkQOxpAJmEyUIt6LgwuGESxdSsDWGd0qv1Vrsa26YzM,3390
1
+ greenmining/__init__.py,sha256=S7eN_NkK3aC68nLMNiVgcPdcVwW-PvbyfY_3ZpHsuQw,3390
2
2
  greenmining/__main__.py,sha256=NYOVS7D4w2XDLn6SyXHXPKE5GrNGOeoWSTb_KazgK5c,590
3
3
  greenmining/__version__.py,sha256=xZc02a8bS3vUJlzh8k9RoxemB1irQmq_SpVVj6Cg5M0,62
4
4
  greenmining/config.py,sha256=M4a7AwM1ErCmOY0n5Vmyoo9HPblSkTZ-HD3k2YHzs4A,8340
@@ -14,8 +14,6 @@ greenmining/analyzers/temporal_analyzer.py,sha256=JfTcAoI20oCFMehGrSRnDqhJTXI-RU
14
14
  greenmining/analyzers/version_power_analyzer.py,sha256=2P6zOqBg-ButtIhF-4cutiwD2Q1geMY49VFUghHXXoI,8119
15
15
  greenmining/controllers/__init__.py,sha256=UiAT6zBvC1z_9cJWfzq1cLA0I4r9b2vURHipj8oDczI,180
16
16
  greenmining/controllers/repository_controller.py,sha256=DM9BabUAwZJARGngCk_4wEYPw2adn8iESCiFQ7Um4LQ,3880
17
- greenmining/dashboard/__init__.py,sha256=Ig_291-hLrH9k3rV0whhQ1EkhiaRR8ciHiJ5s5OCBf4,141
18
- greenmining/dashboard/app.py,sha256=Hk6_i2qmcg6SGW7UzxglEIvUBJiloRA-hMYI-YSORcA,8604
19
17
  greenmining/energy/__init__.py,sha256=GoCYh7hitWBoPMtan1HF1yezCHi7o4sa_YUJgGkeJc8,558
20
18
  greenmining/energy/base.py,sha256=3hIPgc4B0Nz9V7DTh2Xd6trDRtmozUBBpa5UWRuWzcw,5918
21
19
  greenmining/energy/carbon_reporter.py,sha256=bKIFlLhHfYzI4DBu_ff4GW1Psz4oSCAF4NmzQb-EShA,8298
@@ -37,8 +35,8 @@ greenmining/services/github_fetcher.py,sha256=sdkS-LhHmX7mgMdlClCwEUVnZrItc0Pt6F
37
35
  greenmining/services/github_graphql_fetcher.py,sha256=ZklXdEAc60KeFL83zRYMwW_-2OwMKpfPY7Wrifl0D50,11539
38
36
  greenmining/services/local_repo_analyzer.py,sha256=pnH_Hf3GjCFovurEl2uZgOgD3qjqcsP2K1QnKHddkSY,24903
39
37
  greenmining/services/reports.py,sha256=Vrw_pBNmVw2mTAf1dpcAqjBe6gXv-O4w_XweoVTt7L8,23392
40
- greenmining-1.1.6.dist-info/licenses/LICENSE,sha256=M7ma3JHGeiIZIs3ea0HTcFl_wLFPX2NZElUliYs4bCA,1083
41
- greenmining-1.1.6.dist-info/METADATA,sha256=ADh-CwQLjdVv3P3BdMI8Ao50u1dPngilhoCTcX-Hr7M,30811
42
- greenmining-1.1.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
43
- greenmining-1.1.6.dist-info/top_level.txt,sha256=nreXgXxZIWI-42yQknQ0HXtUrFnzZ8N1ra4Mdy2KcsI,12
44
- greenmining-1.1.6.dist-info/RECORD,,
38
+ greenmining-1.1.7.dist-info/licenses/LICENSE,sha256=M7ma3JHGeiIZIs3ea0HTcFl_wLFPX2NZElUliYs4bCA,1083
39
+ greenmining-1.1.7.dist-info/METADATA,sha256=LiRreZ7kVcsr76DZHlkyTcBD7u58IokOvJe4lfDu3vw,30280
40
+ greenmining-1.1.7.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
41
+ greenmining-1.1.7.dist-info/top_level.txt,sha256=nreXgXxZIWI-42yQknQ0HXtUrFnzZ8N1ra4Mdy2KcsI,12
42
+ greenmining-1.1.7.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- # Web dashboard module for GreenMining visualization.
2
-
3
- from .app import create_app, run_dashboard
4
-
5
- __all__ = ["create_app", "run_dashboard"]
@@ -1,200 +0,0 @@
1
- # Flask-based web dashboard for GreenMining analysis visualization.
2
- # Provides interactive charts for repository analysis, pattern distribution,
3
- # temporal trends, and energy consumption.
4
-
5
- from __future__ import annotations
6
-
7
- import json
8
- from pathlib import Path
9
- from typing import Any, Dict, List, Optional
10
-
11
-
12
- def create_app(data_dir: str = "./data"):
13
- # Create Flask application for the dashboard.
14
- # Args:
15
- # data_dir: Path to directory containing analysis JSON files
16
- # Returns:
17
- # Flask application instance
18
- try:
19
- from flask import Flask, render_template_string, jsonify, request
20
- except ImportError:
21
- raise ImportError("Flask is required for the dashboard. Install it with: pip install flask")
22
-
23
- app = Flask(__name__)
24
- data_path = Path(data_dir)
25
-
26
- def _load_data(filename: str) -> Dict[str, Any]:
27
- filepath = data_path / filename
28
- if filepath.exists():
29
- with open(filepath, encoding="utf-8") as f:
30
- return json.load(f)
31
- return {}
32
-
33
- @app.route("/")
34
- def index():
35
- return render_template_string(DASHBOARD_HTML)
36
-
37
- @app.route("/api/repositories")
38
- def api_repositories():
39
- data = _load_data("repositories.json")
40
- return jsonify(data)
41
-
42
- @app.route("/api/analysis")
43
- def api_analysis():
44
- data = _load_data("analysis_results.json")
45
- return jsonify(data)
46
-
47
- @app.route("/api/statistics")
48
- def api_statistics():
49
- data = _load_data("aggregated_statistics.json")
50
- return jsonify(data)
51
-
52
- @app.route("/api/energy")
53
- def api_energy():
54
- data = _load_data("energy_report.json")
55
- return jsonify(data)
56
-
57
- @app.route("/api/summary")
58
- def api_summary():
59
- # Build summary from available data
60
- repos = _load_data("repositories.json")
61
- analysis = _load_data("analysis_results.json")
62
-
63
- repo_count = 0
64
- if isinstance(repos, list):
65
- repo_count = len(repos)
66
- elif isinstance(repos, dict):
67
- repo_count = repos.get("total_repositories", len(repos.get("repositories", [])))
68
-
69
- commit_count = 0
70
- green_count = 0
71
- if isinstance(analysis, list):
72
- commit_count = len(analysis)
73
- green_count = sum(1 for a in analysis if a.get("green_aware"))
74
- elif isinstance(analysis, dict):
75
- results = analysis.get("results", [])
76
- for r in results:
77
- commits = r.get("commits", [])
78
- commit_count += len(commits)
79
- green_count += sum(1 for c in commits if c.get("green_aware"))
80
-
81
- green_rate = (green_count / commit_count * 100) if commit_count > 0 else 0
82
-
83
- return jsonify(
84
- {
85
- "repositories": repo_count,
86
- "commits_analyzed": commit_count,
87
- "green_commits": green_count,
88
- "green_rate": round(green_rate, 1),
89
- }
90
- )
91
-
92
- return app
93
-
94
-
95
- def run_dashboard(data_dir: str = "./data", host: str = "127.0.0.1", port: int = 5000):
96
- # Run the dashboard server.
97
- # Args:
98
- # data_dir: Path to analysis data directory
99
- # host: Host to bind to
100
- # port: Port to bind to
101
- app = create_app(data_dir)
102
- print(f"GreenMining Dashboard running at http://{host}:{port}")
103
- print(f"Data directory: {data_dir}")
104
- app.run(host=host, port=port, debug=False)
105
-
106
-
107
- # Dashboard HTML template with embedded JS (no external dependencies)
108
- DASHBOARD_HTML = """
109
- <!DOCTYPE html>
110
- <html lang="en">
111
- <head>
112
- <meta charset="UTF-8">
113
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
114
- <title>GreenMining Dashboard</title>
115
- <style>
116
- * { margin: 0; padding: 0; box-sizing: border-box; }
117
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
118
- background: #f5f7fa; color: #333; }
119
- .header { background: #1a472a; color: white; padding: 20px 40px; }
120
- .header h1 { font-size: 24px; font-weight: 600; }
121
- .header p { font-size: 14px; opacity: 0.8; margin-top: 4px; }
122
- .container { max-width: 1200px; margin: 0 auto; padding: 20px; }
123
- .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }
124
- .card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
125
- .card h3 { font-size: 13px; color: #666; text-transform: uppercase; letter-spacing: 0.5px; }
126
- .card .value { font-size: 32px; font-weight: 700; color: #1a472a; margin-top: 8px; }
127
- .card .subtitle { font-size: 12px; color: #999; margin-top: 4px; }
128
- .section { margin-bottom: 24px; }
129
- .section h2 { font-size: 18px; margin-bottom: 12px; color: #1a472a; }
130
- table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px;
131
- overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
132
- th, td { padding: 12px 16px; text-align: left; border-bottom: 1px solid #eee; }
133
- th { background: #f8f9fa; font-size: 12px; text-transform: uppercase; color: #666; }
134
- td { font-size: 14px; }
135
- .badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; }
136
- .badge-green { background: #d4edda; color: #155724; }
137
- .badge-gray { background: #e9ecef; color: #495057; }
138
- .bar { height: 8px; background: #e9ecef; border-radius: 4px; overflow: hidden; }
139
- .bar-fill { height: 100%; background: #1a472a; border-radius: 4px;
140
- transition: width 0.5s ease; }
141
- .loading { text-align: center; padding: 40px; color: #999; }
142
- </style>
143
- </head>
144
- <body>
145
- <div class="header">
146
- <h1>GreenMining Dashboard</h1>
147
- <p>Mining Software Repositories for Green IT Research</p>
148
- </div>
149
- <div class="container">
150
- <div class="grid" id="summary-cards">
151
- <div class="card"><h3>Repositories</h3><div class="value" id="repo-count">-</div></div>
152
- <div class="card"><h3>Commits Analyzed</h3><div class="value" id="commit-count">-</div></div>
153
- <div class="card"><h3>Green Commits</h3><div class="value" id="green-count">-</div></div>
154
- <div class="card"><h3>Green Rate</h3><div class="value" id="green-rate">-</div></div>
155
- </div>
156
- <div class="section">
157
- <h2>Repositories</h2>
158
- <div id="repo-table"><div class="loading">Loading data...</div></div>
159
- </div>
160
- </div>
161
- <script>
162
- async function loadDashboard() {
163
- try {
164
- const summary = await fetch('/api/summary').then(r => r.json());
165
- document.getElementById('repo-count').textContent = summary.repositories;
166
- document.getElementById('commit-count').textContent = summary.commits_analyzed.toLocaleString();
167
- document.getElementById('green-count').textContent = summary.green_commits.toLocaleString();
168
- document.getElementById('green-rate').textContent = summary.green_rate + '%';
169
- } catch(e) {
170
- console.log('Summary not available:', e);
171
- }
172
-
173
- try {
174
- const repos = await fetch('/api/repositories').then(r => r.json());
175
- const list = repos.repositories || (Array.isArray(repos) ? repos : []);
176
- if (list.length > 0) {
177
- let html = '<table><thead><tr><th>Repository</th><th>Language</th>' +
178
- '<th>Stars</th><th>Description</th></tr></thead><tbody>';
179
- list.slice(0, 50).forEach(r => {
180
- html += '<tr><td><strong>' + (r.full_name || r.name) + '</strong></td>' +
181
- '<td><span class="badge badge-green">' + (r.language || '-') + '</span></td>' +
182
- '<td>' + (r.stars || 0).toLocaleString() + '</td>' +
183
- '<td>' + (r.description || '-').substring(0, 80) + '</td></tr>';
184
- });
185
- html += '</tbody></table>';
186
- document.getElementById('repo-table').innerHTML = html;
187
- } else {
188
- document.getElementById('repo-table').innerHTML =
189
- '<div class="card">No repository data found. Run an analysis first.</div>';
190
- }
191
- } catch(e) {
192
- document.getElementById('repo-table').innerHTML =
193
- '<div class="card">Run an analysis to populate the dashboard.</div>';
194
- }
195
- }
196
- loadDashboard();
197
- </script>
198
- </body>
199
- </html>
200
- """