metripy 0.3.2__tar.gz → 0.3.6__tar.gz

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.

Potentially problematic release.


This version of metripy might be problematic. Click here for more details.

Files changed (104) hide show
  1. metripy-0.3.6/CHANGELOG.md +64 -0
  2. metripy-0.3.6/MANIFEST.in +7 -0
  3. {metripy-0.3.2 → metripy-0.3.6}/PKG-INFO +2 -2
  4. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/File/ConfigFileReaderInterface.py +1 -1
  5. metripy-0.3.6/metripy/Application/Info.py +61 -0
  6. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/DependencyPageRenderer.py +2 -2
  7. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/IndexPageRenderer.py +7 -0
  8. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/Reporter.py +34 -7
  9. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/TrendsPageRenderer.py +23 -0
  10. metripy-0.3.6/metripy/templates/html_report/css/styles.css +1386 -0
  11. metripy-0.3.6/metripy/templates/html_report/dependencies.html +411 -0
  12. metripy-0.3.6/metripy/templates/html_report/files.html +1080 -0
  13. metripy-0.3.6/metripy/templates/html_report/git_analysis.html +325 -0
  14. metripy-0.3.6/metripy/templates/html_report/images/logo.svg +31 -0
  15. metripy-0.3.6/metripy/templates/html_report/index.html +374 -0
  16. metripy-0.3.6/metripy/templates/html_report/js/charts.js +313 -0
  17. metripy-0.3.6/metripy/templates/html_report/js/dashboard.js +546 -0
  18. metripy-0.3.6/metripy/templates/html_report/js/git_analysis.js +383 -0
  19. metripy-0.3.6/metripy/templates/html_report/top_offenders.html +267 -0
  20. metripy-0.3.6/metripy/templates/html_report/trends.html +468 -0
  21. {metripy-0.3.2 → metripy-0.3.6}/metripy.egg-info/PKG-INFO +2 -2
  22. {metripy-0.3.2 → metripy-0.3.6}/metripy.egg-info/SOURCES.txt +14 -1
  23. {metripy-0.3.2 → metripy-0.3.6}/metripy.egg-info/requires.txt +1 -1
  24. {metripy-0.3.2 → metripy-0.3.6}/pyproject.toml +14 -2
  25. metripy-0.3.2/metripy/Application/Info.py +0 -36
  26. {metripy-0.3.2 → metripy-0.3.6}/LICENSE +0 -0
  27. {metripy-0.3.2 → metripy-0.3.6}/README.md +0 -0
  28. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Analyzer.py +0 -0
  29. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Application.py +0 -0
  30. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/Config.py +0 -0
  31. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/File/ConfigFileReaderFactory.py +0 -0
  32. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/File/JsonConfigFileReader.py +0 -0
  33. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/File/YamlConfigFileReader.py +0 -0
  34. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/GitConfig.py +0 -0
  35. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/Parser.py +0 -0
  36. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/ProjectConfig.py +0 -0
  37. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/Config/ReportConfig.py +0 -0
  38. {metripy-0.3.2 → metripy-0.3.6}/metripy/Application/__init__.py +0 -0
  39. {metripy-0.3.2 → metripy-0.3.6}/metripy/Component/Debug/Debugger.py +0 -0
  40. {metripy-0.3.2 → metripy-0.3.6}/metripy/Component/File/Finder.py +0 -0
  41. {metripy-0.3.2 → metripy-0.3.6}/metripy/Component/Output/CliOutput.py +0 -0
  42. {metripy-0.3.2 → metripy-0.3.6}/metripy/Component/Output/ProgressBar.py +0 -0
  43. {metripy-0.3.2 → metripy-0.3.6}/metripy/Dependency/Composer/Composer.py +0 -0
  44. {metripy-0.3.2 → metripy-0.3.6}/metripy/Dependency/Composer/Packegist.py +0 -0
  45. {metripy-0.3.2 → metripy-0.3.6}/metripy/Dependency/Dependency.py +0 -0
  46. {metripy-0.3.2 → metripy-0.3.6}/metripy/Dependency/Npm/Npm.py +0 -0
  47. {metripy-0.3.2 → metripy-0.3.6}/metripy/Dependency/Npm/NpmOrg.py +0 -0
  48. {metripy-0.3.2 → metripy-0.3.6}/metripy/Dependency/Pip/Pip.py +0 -0
  49. {metripy-0.3.2 → metripy-0.3.6}/metripy/Dependency/Pip/PyPi.py +0 -0
  50. {metripy-0.3.2 → metripy-0.3.6}/metripy/Git/GitAnalyzer.py +0 -0
  51. {metripy-0.3.2 → metripy-0.3.6}/metripy/Import/Json/JsonImporter.py +0 -0
  52. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/AbstractLangAnalyzer.py +0 -0
  53. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Generic/HalSteadAnalyzer.py +0 -0
  54. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Generic/__init__.py +0 -0
  55. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Php/PhpAnalyzer.py +0 -0
  56. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Php/PhpBasicAstParser.py +0 -0
  57. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Php/PhpBasicLocAnalyzer.py +0 -0
  58. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Php/PhpHalSteadAnalyzer.py +0 -0
  59. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Python/PythonAnalyzer.py +0 -0
  60. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Python/PythonHalSteadAnalyzer.py +0 -0
  61. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Typescript/TypescriptAnalyzer.py +0 -0
  62. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Typescript/TypescriptAstParser.py +0 -0
  63. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Typescript/TypescriptBasicComplexityAnalyzer.py +0 -0
  64. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Typescript/TypescriptBasicLocAnalyzer.py +0 -0
  65. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/Typescript/TypescriptHalSteadAnalyzer.py +0 -0
  66. {metripy-0.3.2 → metripy-0.3.6}/metripy/LangAnalyzer/__init__.py +0 -0
  67. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Code/AggregatedMetrics.py +0 -0
  68. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Code/FileMetrics.py +0 -0
  69. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Code/ModuleMetrics.py +0 -0
  70. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Code/SegmentedMetrics.py +0 -0
  71. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Code/Segmentor.py +0 -0
  72. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/FileTree/FileTree.py +0 -0
  73. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/FileTree/FileTreeParser.py +0 -0
  74. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Git/GitCodeHotspot.py +0 -0
  75. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Git/GitContributor.py +0 -0
  76. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Git/GitKnowledgeSilo.py +0 -0
  77. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Git/GitMetrics.py +0 -0
  78. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/ProjectMetrics.py +0 -0
  79. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Trend/AggregatedTrendMetric.py +0 -0
  80. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Trend/ClassTrendMetric.py +0 -0
  81. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Trend/FileTrendMetric.py +0 -0
  82. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Trend/FunctionTrendMetric.py +0 -0
  83. {metripy-0.3.2 → metripy-0.3.6}/metripy/Metric/Trend/SegmentedTrendMetric.py +0 -0
  84. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Csv/Reporter.py +0 -0
  85. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/FilesPageRenderer.py +0 -0
  86. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/GitAnalysisPageRenderer.py +0 -0
  87. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/PageRenderer.py +0 -0
  88. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/PageRendererFactory.py +0 -0
  89. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Html/TopOffendersPageRenderer.py +0 -0
  90. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Json/AbstractJsonReporter.py +0 -0
  91. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Json/GitJsonReporter.py +0 -0
  92. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/Json/JsonReporter.py +0 -0
  93. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/ReporterFactory.py +0 -0
  94. {metripy-0.3.2 → metripy-0.3.6}/metripy/Report/ReporterInterface.py +0 -0
  95. {metripy-0.3.2 → metripy-0.3.6}/metripy/Tree/ClassNode.py +0 -0
  96. {metripy-0.3.2 → metripy-0.3.6}/metripy/Tree/FunctionNode.py +0 -0
  97. {metripy-0.3.2 → metripy-0.3.6}/metripy/Tree/ModuleNode.py +0 -0
  98. {metripy-0.3.2 → metripy-0.3.6}/metripy/Trend/TrendAnalyzer.py +0 -0
  99. {metripy-0.3.2 → metripy-0.3.6}/metripy/__init__.py +0 -0
  100. {metripy-0.3.2 → metripy-0.3.6}/metripy/metripy.py +0 -0
  101. {metripy-0.3.2 → metripy-0.3.6}/metripy.egg-info/dependency_links.txt +0 -0
  102. {metripy-0.3.2 → metripy-0.3.6}/metripy.egg-info/entry_points.txt +0 -0
  103. {metripy-0.3.2 → metripy-0.3.6}/metripy.egg-info/top_level.txt +0 -0
  104. {metripy-0.3.2 → metripy-0.3.6}/setup.cfg +0 -0
@@ -0,0 +1,64 @@
1
+ # v0.3.6
2
+ - Fix dependency license distribution chart
3
+
4
+ # v0.3.5
5
+ - Bump templater version
6
+ - Fix path resolving
7
+ - Fix error during trends rendering
8
+
9
+ # v0.3.4
10
+ - Fix version info after install
11
+
12
+ # v0.3.3
13
+ - Fix missing templates after install
14
+
15
+ # v0.3.2
16
+ - Add missing dependency
17
+
18
+ # v0.3.1
19
+ - Add yaml config support
20
+ - Clean up html page rendering
21
+
22
+ # v0.3.0
23
+ - Add trends
24
+
25
+ # v0.2.8
26
+ - Fix version status in pip analysis
27
+ - Add json report
28
+
29
+ # v0.2.7
30
+ - fix files
31
+
32
+ # v0.2.6
33
+ - Fully move namespace, fix script
34
+
35
+ # v0.2.5
36
+ - Change name of project to metripy
37
+
38
+ # v0.2.4
39
+ - Change name of project to py_codemetrics
40
+
41
+ # v0.2.3
42
+ - Fix test action by dropping 3.9, 3.10 support
43
+
44
+ # v0.2.2
45
+ - Fix test action
46
+
47
+ # v0.2.1
48
+ - Added git metrics json reporting
49
+ - Added some first tests
50
+ - Added github actions
51
+
52
+ # v0.2.0
53
+ - Added code analysis of typescript
54
+ - Added npm dependencies analysis
55
+
56
+ # v0.1.0
57
+ - Added main structure
58
+ - Added config loading and parsing
59
+ - Added code analysis of python
60
+ - Added code analysis of php
61
+ - Added git analysis
62
+ - Added composer dependencies analysis
63
+ - Added pip dependencies analysis
64
+ - Added html report dashboard, file insights, git insights, dependency insights
@@ -0,0 +1,7 @@
1
+ recursive-include metripy/templates *
2
+ include metripy/logo.svg
3
+ include logo.svg
4
+ include README.md
5
+ include LICENSE
6
+ include CHANGELOG.md
7
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metripy
3
- Version: 0.3.2
3
+ Version: 0.3.6
4
4
  Summary: A Python tool to generate multi project, multi language code metric reports
5
5
  Author-email: Yannick Zimmermann <yannick.zimmermann@proton.me>
6
6
  License: MIT
@@ -19,7 +19,7 @@ Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: lizard==1.18.0
21
21
  Requires-Dist: GitPython==3.1.45
22
- Requires-Dist: py-template-engine>=0.1.0
22
+ Requires-Dist: py-template-engine>=0.2.6
23
23
  Requires-Dist: radon==6.0.1
24
24
  Requires-Dist: requests==2.32.5
25
25
  Requires-Dist: packaging==25.0
@@ -16,7 +16,7 @@ class ConfigFileReaderInterface(ABC):
16
16
  pass
17
17
 
18
18
  def resolve_path(self, path: str) -> str:
19
- return os.path.join(os.path.dirname(self.filename), path)
19
+ return path
20
20
 
21
21
  def parse_data(self, data: dict, config: Config) -> None:
22
22
  # configs
@@ -0,0 +1,61 @@
1
+ from importlib.metadata import version, metadata
2
+ import toml
3
+
4
+
5
+ class Info:
6
+ def __init__(self):
7
+ self.version = self._get_version()
8
+ self.url = self._get_homepage_url()
9
+
10
+ def _get_pyproject_data(self) -> dict:
11
+ with open("pyproject.toml", "r") as file:
12
+ data = toml.load(file)
13
+ return data
14
+
15
+ def _get_version(self) -> str:
16
+ """Get version from installed package metadata"""
17
+ try:
18
+ return version("metripy")
19
+ except Exception:
20
+ # Fallback for development if not installed
21
+ return self._get_pyproject_data()["project"]["version"]
22
+
23
+ def _get_homepage_url(self) -> str:
24
+ """Get homepage URL from installed package metadata"""
25
+ try:
26
+ meta = metadata("metripy")
27
+ # Try to get Home-Page from metadata
28
+ homepage = meta.get("Home-Page")
29
+ if not homepage:
30
+ # Try Project-URL field
31
+ for line in meta.get_all("Project-URL") or []:
32
+ if line.startswith("Homepage"):
33
+ homepage = line.split(",", 1)[1].strip()
34
+ break
35
+ return homepage or "no homepage found"
36
+ except Exception:
37
+ # Fallback
38
+ return self._get_pyproject_data()["project"]["urls"]["Homepage"]
39
+
40
+ def get_version(self) -> str:
41
+ return self.version
42
+
43
+ def get_version_info(self) -> str:
44
+ return f"""
45
+ Metripy {self.get_version()}
46
+ {self.url}
47
+ """
48
+
49
+ def get_help(self) -> str:
50
+ return (
51
+ self.get_version_info()
52
+ + """
53
+ Usage: metripy [options]
54
+ Options:
55
+ --config=<file> Use a custom config file
56
+ --version Show the version and exit
57
+ --help Show this help message and exit
58
+ --debug Enable debug mode
59
+ --quiet Disable output
60
+ """
61
+ )
@@ -1,7 +1,7 @@
1
1
  from metripy.Dependency.Dependency import Dependency
2
2
  from metripy.Metric.ProjectMetrics import ProjectMetrics
3
3
  from metripy.Report.Html.PageRenderer import PageRenderer
4
-
4
+ import json
5
5
 
6
6
  class DependencyPageRenderer(PageRenderer):
7
7
  def __init__(self, template_dir: str, output_dir: str, project_name: str):
@@ -16,6 +16,6 @@ class DependencyPageRenderer(PageRenderer):
16
16
  {
17
17
  "has_dependencies_data": bool(metrics.dependencies),
18
18
  "dependencies": [d.to_dict() for d in dependencies],
19
- "license_distribution": license_by_type,
19
+ "license_distribution_json": json.dumps(license_by_type, indent=2),
20
20
  },
21
21
  )
@@ -3,6 +3,8 @@ import json
3
3
  from metripy.Metric.ProjectMetrics import ProjectMetrics
4
4
  from metripy.Report.Html.PageRenderer import PageRenderer
5
5
 
6
+ from metripy.Dependency.Dependency import Dependency
7
+
6
8
 
7
9
  class IndexPageRenderer(PageRenderer):
8
10
  def __init__(self, template_dir: str, output_dir: str, project_name: str):
@@ -13,10 +15,15 @@ class IndexPageRenderer(PageRenderer):
13
15
  if metrics.git_metrics:
14
16
  git_stats_data = metrics.git_metrics.get_commit_stats_per_month()
15
17
 
18
+
19
+ dependencies = metrics.dependencies if metrics.dependencies is not None else []
20
+ license_by_type = Dependency.get_lisence_distribution(dependencies)
21
+
16
22
  self.render_template(
17
23
  "index.html",
18
24
  {
19
25
  "git_stats_data": json.dumps(git_stats_data, indent=4),
26
+ "license_distribution_json": json.dumps(license_by_type, indent=2),
20
27
  "total_code_metrics": metrics.total_code_metrics.to_dict(),
21
28
  "has_total_code_metrics_trend": metrics.total_code_metrics.trend
22
29
  is not None,
@@ -1,6 +1,8 @@
1
1
  import os
2
2
  import shutil
3
+ import sys
3
4
  from datetime import datetime
5
+ from pathlib import Path
4
6
 
5
7
 
6
8
  from metripy.Application.Config.ReportConfig import ReportConfig
@@ -16,7 +18,16 @@ class Reporter(ReporterInterface):
16
18
  ):
17
19
  self.config: ReportConfig = config
18
20
  self.output = output
19
- self.template_dir = os.path.join(os.getcwd(), "templates/html_report")
21
+
22
+ # Find templates directory - works both in development and when installed
23
+ template_dir = self._find_template_dir()
24
+ if not template_dir.exists():
25
+ raise FileNotFoundError(
26
+ f"Could not find templates directory. Searched in: "
27
+ f"{template_dir}"
28
+ )
29
+
30
+ self.template_dir = str(template_dir)
20
31
  self.project_name = project_name
21
32
 
22
33
  self.page_renderer_factory = PageRendererFactory(
@@ -27,6 +38,28 @@ class Reporter(ReporterInterface):
27
38
  "project_name": project_name,
28
39
  "last_updated": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
29
40
  }
41
+
42
+ def _find_template_dir(self) -> Path:
43
+ """Find the templates directory, checking multiple possible locations"""
44
+ package_dir = Path(__file__).parent.parent.parent # metripy package root
45
+
46
+ # List of possible locations to check
47
+ possible_locations = [
48
+ # Development: templates at project root
49
+ package_dir.parent / "templates" / "html_report",
50
+ # Alternative: templates inside metripy package
51
+ package_dir / "templates" / "html_report",
52
+ # System install location
53
+ Path(sys.prefix) / "share" / "metripy" / "templates" / "html_report",
54
+ # Fallback to cwd (for development)
55
+ Path.cwd() / "metripy" / "templates" / "html_report",
56
+ ]
57
+
58
+ for location in possible_locations:
59
+ if location.exists() and (location / "index.html").exists():
60
+ return location
61
+
62
+ return possible_locations[0]
30
63
 
31
64
  def generate(self, metrics: ProjectMetrics):
32
65
 
@@ -63,12 +96,6 @@ class Reporter(ReporterInterface):
63
96
  )
64
97
  # shutil.copytree(os.path.join(self.template_dir, "fonts"), os.path.join(self.config.path, "fonts"), dirs_exist_ok=True)
65
98
 
66
- # copy logo, lies 2 down from the templates directory
67
- shutil.copy(
68
- os.path.join(self.template_dir, "../..", "logo.svg"),
69
- os.path.join(self.config.path, "images", "logo.svg"),
70
- )
71
-
72
99
  # Render main pages
73
100
  self.render_index_page(metrics)
74
101
  self.render_files_page(metrics)
@@ -22,6 +22,29 @@ class TrendsPageRenderer(PageRenderer):
22
22
  }
23
23
 
24
24
  def render(self, metrics: ProjectMetrics):
25
+ if metrics.total_code_metrics.trend is None:
26
+ self.render_template(
27
+ "trends.html",
28
+ {
29
+ "has_trend_data": False,
30
+ "trend_data": {
31
+ "top_improved_complexity": [],
32
+ "top_improved_maintainability": [],
33
+ "top_worsened_complexity": [],
34
+ "top_worsened_maintainability": [],
35
+ "loc_segments_current": {},
36
+ "loc_segments_prev": {},
37
+ "complexity_segments_current": {},
38
+ "complexity_segments_prev": {},
39
+ "maintainability_segments_current": {},
40
+ "maintainability_segments_prev": {},
41
+ "method_size_segments_current": {},
42
+ "method_size_segments_prev": {},
43
+ },
44
+ },
45
+ )
46
+ return
47
+
25
48
  # Top improved complexity (complexity went down - negative delta)
26
49
  top_improved_complexity = [
27
50
  x