codemri 0.1.0__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.
codemri-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,89 @@
1
+ Metadata-Version: 2.4
2
+ Name: codemri
3
+ Version: 0.1.0
4
+ Summary: Instant code quality reports for your Python projects — style, complexity, and an overall health score in one command
5
+ Author-email: Suzzane Koranteng <korantengsuzzane@gmail.com>
6
+ License-Expression: MIT
7
+ Keywords: code quality,linting,complexity,cli,developer tools,static analysis
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Software Development :: Quality Assurance
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: typer>=0.9.0
16
+ Requires-Dist: rich>=13.0.0
17
+ Requires-Dist: ruff>=0.4.0
18
+ Requires-Dist: radon>=6.0.0
19
+
20
+ # CodeMRI
21
+
22
+ **Instant code quality reports for your Python projects.**
23
+
24
+ CodeMRI scans your codebase and gives you a single, easy-to-read health score — combining style violations and code complexity into one number, so you know exactly how healthy your code is and where to focus first.
25
+
26
+ ## Why CodeMRI?
27
+
28
+ Most linters dump a wall of warnings and leave you to figure out what matters. CodeMRI instead gives you:
29
+
30
+ - **One overall health score (0–100)** with a letter grade — like an MRI scan for your code
31
+ - **A "Worst Offenders" leaderboard** — the exact functions and files causing the most pain, ranked by severity
32
+ - **A clean, shareable HTML report** — perfect for pasting into a PR or sharing with your team
33
+ - **Score history tracking** — see whether your codebase is improving or rotting over time, right from the CLI
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install codemri
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ Scan the current directory:
44
+
45
+ ```bash
46
+ codemri scan .
47
+ ```
48
+
49
+ Scan a specific file or folder:
50
+
51
+ ```bash
52
+ codemri scan path/to/project
53
+ ```
54
+
55
+ Generate a shareable HTML report:
56
+
57
+ ```bash
58
+ codemri scan . --html
59
+ ```
60
+
61
+ View your score history over time:
62
+
63
+ ```bash
64
+ codemri history .
65
+ ```
66
+
67
+ Check the installed version:
68
+
69
+ ```bash
70
+ codemri --version
71
+ ```
72
+
73
+ ## Example output
74
+
75
+ ────────────────── Overall Code Health ──────────────────╮
76
+ │ 69/100 Grade: C │
77
+ ╰────────────────────────────────────────────────────────╯
78
+ Style score: 39/100 (9 issues across 59 lines)
79
+ Complexity score: 98/100 (1 files analyzed)
80
+
81
+ ## How scoring works
82
+
83
+ - **Style score** — based on the density of style/lint issues (via [ruff](https://github.com/astral-sh/ruff)) relative to lines of code
84
+ - **Complexity score** — based on cyclomatic complexity rankings (via [radon](https://github.com/rubik/radon)) across all functions
85
+ - **Overall score** — a 50/50 weighted average of the two, mapped to a letter grade (A–F)
86
+
87
+ ## License
88
+
89
+ MIT
@@ -0,0 +1,70 @@
1
+ # CodeMRI
2
+
3
+ **Instant code quality reports for your Python projects.**
4
+
5
+ CodeMRI scans your codebase and gives you a single, easy-to-read health score — combining style violations and code complexity into one number, so you know exactly how healthy your code is and where to focus first.
6
+
7
+ ## Why CodeMRI?
8
+
9
+ Most linters dump a wall of warnings and leave you to figure out what matters. CodeMRI instead gives you:
10
+
11
+ - **One overall health score (0–100)** with a letter grade — like an MRI scan for your code
12
+ - **A "Worst Offenders" leaderboard** — the exact functions and files causing the most pain, ranked by severity
13
+ - **A clean, shareable HTML report** — perfect for pasting into a PR or sharing with your team
14
+ - **Score history tracking** — see whether your codebase is improving or rotting over time, right from the CLI
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install codemri
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ Scan the current directory:
25
+
26
+ ```bash
27
+ codemri scan .
28
+ ```
29
+
30
+ Scan a specific file or folder:
31
+
32
+ ```bash
33
+ codemri scan path/to/project
34
+ ```
35
+
36
+ Generate a shareable HTML report:
37
+
38
+ ```bash
39
+ codemri scan . --html
40
+ ```
41
+
42
+ View your score history over time:
43
+
44
+ ```bash
45
+ codemri history .
46
+ ```
47
+
48
+ Check the installed version:
49
+
50
+ ```bash
51
+ codemri --version
52
+ ```
53
+
54
+ ## Example output
55
+
56
+ ────────────────── Overall Code Health ──────────────────╮
57
+ │ 69/100 Grade: C │
58
+ ╰────────────────────────────────────────────────────────╯
59
+ Style score: 39/100 (9 issues across 59 lines)
60
+ Complexity score: 98/100 (1 files analyzed)
61
+
62
+ ## How scoring works
63
+
64
+ - **Style score** — based on the density of style/lint issues (via [ruff](https://github.com/astral-sh/ruff)) relative to lines of code
65
+ - **Complexity score** — based on cyclomatic complexity rankings (via [radon](https://github.com/rubik/radon)) across all functions
66
+ - **Overall score** — a 50/50 weighted average of the two, mapped to a letter grade (A–F)
67
+
68
+ ## License
69
+
70
+ MIT
File without changes
@@ -0,0 +1,365 @@
1
+ import subprocess
2
+ import json
3
+ import os
4
+ import sqlite3
5
+ from datetime import datetime
6
+ import typer
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+ from rich.panel import Panel
10
+
11
+ app = typer.Typer(help="Instant code quality reports for your Python projects")
12
+ console = Console()
13
+
14
+ RADON_RANK_PENALTY = {
15
+ "A": 0,
16
+ "B": 5,
17
+ "C": 15,
18
+ "D": 30,
19
+ "E": 45,
20
+ "F": 60,
21
+ }
22
+
23
+ GRADE_COLORS = {
24
+ "A": "#22c55e",
25
+ "B": "#84cc16",
26
+ "C": "#eab308",
27
+ "D": "#f97316",
28
+ "F": "#ef4444",
29
+ }
30
+
31
+
32
+ def run_ruff(path: str):
33
+ result = subprocess.run(
34
+ ["ruff", "check", path, "--output-format=json"],
35
+ capture_output=True,
36
+ text=True,
37
+ )
38
+ if not result.stdout.strip():
39
+ return []
40
+ try:
41
+ return json.loads(result.stdout)
42
+ except json.JSONDecodeError:
43
+ return []
44
+
45
+
46
+ def run_radon_complexity(path: str):
47
+ result = subprocess.run(
48
+ ["radon", "cc", path, "-j", "-e", "venv/*,*/venv/*,.venv/*,*/.venv/*"],
49
+ capture_output=True,
50
+ text=True,
51
+ )
52
+ if not result.stdout.strip():
53
+ return {}
54
+ try:
55
+ return json.loads(result.stdout)
56
+ except json.JSONDecodeError:
57
+ return {}
58
+
59
+
60
+ def count_lines_of_code(path: str, complexity_data: dict) -> int:
61
+ total = 0
62
+ for file in complexity_data.keys():
63
+ try:
64
+ with open(file, "r", encoding="utf-8", errors="ignore") as f:
65
+ total += sum(1 for _ in f)
66
+ except (FileNotFoundError, OSError):
67
+ continue
68
+ return max(total, 1)
69
+
70
+
71
+ def calculate_style_score(issues: list, loc: int) -> float:
72
+ issues_per_100_lines = (len(issues) / loc) * 100
73
+ score = 100 - (issues_per_100_lines * 4)
74
+ return max(0, min(100, score))
75
+
76
+
77
+ def calculate_complexity_score(complexity_data: dict) -> float:
78
+ all_blocks = [block for blocks in complexity_data.values() for block in blocks]
79
+ if not all_blocks:
80
+ return 100.0
81
+ total_penalty = sum(RADON_RANK_PENALTY.get(b.get("rank", "A"), 0) for b in all_blocks)
82
+ avg_penalty = total_penalty / len(all_blocks)
83
+ score = 100 - avg_penalty
84
+ return max(0, min(100, score))
85
+
86
+
87
+ def grade_and_color(score: float):
88
+ if score >= 90:
89
+ return "A", "bright_green"
90
+ elif score >= 75:
91
+ return "B", "green"
92
+ elif score >= 60:
93
+ return "C", "yellow"
94
+ elif score >= 40:
95
+ return "D", "orange3"
96
+ else:
97
+ return "F", "red"
98
+
99
+
100
+ def build_worst_offenders(complexity_data: dict, issues: list, limit: int = 5):
101
+ issues_per_file = {}
102
+ for issue in issues:
103
+ fname = issue.get("filename", "")
104
+ issues_per_file[fname] = issues_per_file.get(fname, 0) + 1
105
+
106
+ offenders = []
107
+ for file, blocks in complexity_data.items():
108
+ file_issue_count = issues_per_file.get(file, 0)
109
+ for block in blocks:
110
+ rank = block.get("rank", "A")
111
+ penalty = RADON_RANK_PENALTY.get(rank, 0)
112
+ severity = penalty + (file_issue_count * 2)
113
+ if severity > 0:
114
+ offenders.append({
115
+ "file": file,
116
+ "function": block.get("name", "?"),
117
+ "complexity": block.get("complexity", "?"),
118
+ "rank": rank,
119
+ "severity": severity,
120
+ })
121
+
122
+ offenders.sort(key=lambda x: x["severity"], reverse=True)
123
+ return offenders[:limit]
124
+
125
+
126
+ def get_db_path(path: str) -> str:
127
+ base_dir = path if os.path.isdir(path) else os.path.dirname(path) or "."
128
+ return os.path.join(base_dir, ".codemri_history.db")
129
+
130
+
131
+ def save_run_to_history(path: str, overall_score: int, style_score: float, complexity_score: float):
132
+ db_path = get_db_path(path)
133
+ conn = sqlite3.connect(db_path)
134
+ cursor = conn.cursor()
135
+ cursor.execute("""
136
+ CREATE TABLE IF NOT EXISTS runs (
137
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
138
+ timestamp TEXT NOT NULL,
139
+ overall_score INTEGER NOT NULL,
140
+ style_score REAL NOT NULL,
141
+ complexity_score REAL NOT NULL
142
+ )
143
+ """)
144
+ cursor.execute(
145
+ "INSERT INTO runs (timestamp, overall_score, style_score, complexity_score) VALUES (?, ?, ?, ?)",
146
+ (datetime.now().isoformat(timespec="seconds"), overall_score, style_score, complexity_score),
147
+ )
148
+ conn.commit()
149
+ conn.close()
150
+
151
+
152
+ def load_history(path: str, limit: int = 10):
153
+ db_path = get_db_path(path)
154
+ if not os.path.exists(db_path):
155
+ return []
156
+ conn = sqlite3.connect(db_path)
157
+ cursor = conn.cursor()
158
+ cursor.execute(
159
+ "SELECT timestamp, overall_score, style_score, complexity_score "
160
+ "FROM runs ORDER BY id DESC LIMIT ?",
161
+ (limit,),
162
+ )
163
+ rows = cursor.fetchall()
164
+ conn.close()
165
+ return list(reversed(rows))
166
+
167
+
168
+ HTML_TEMPLATE = """<!DOCTYPE html>
169
+ <html>
170
+ <head>
171
+ <meta charset="UTF-8">
172
+ <title>CodeMRI Code Quality Report</title>
173
+ <style>
174
+ body { font-family: -apple-system, Segoe UI, sans-serif; background: #0f172a; color: #e2e8f0; padding: 40px; }
175
+ h1 { color: #f8fafc; }
176
+ .score-panel { background: #1e293b; border-left: 6px solid __COLOR__; padding: 24px; border-radius: 8px; margin: 20px 0; }
177
+ .score { font-size: 48px; font-weight: bold; color: __COLOR__; }
178
+ .grade { font-size: 24px; color: __COLOR__; }
179
+ .subscore { display: inline-block; margin-right: 40px; margin-top: 10px; }
180
+ table { width: 100%; border-collapse: collapse; margin-top: 16px; background: #1e293b; border-radius: 8px; overflow: hidden; }
181
+ th { background: #334155; text-align: left; padding: 10px; color: #94a3b8; }
182
+ td { padding: 10px; border-top: 1px solid #334155; font-size: 14px; }
183
+ .badge { padding: 2px 10px; border-radius: 4px; color: white; font-weight: bold; }
184
+ .section-title { margin-top: 40px; color: #f8fafc; }
185
+ .meta { color: #64748b; font-size: 13px; }
186
+ </style>
187
+ </head>
188
+ <body>
189
+ <h1>CodeMRI Code Quality Report</h1>
190
+ <p class="meta">Path: __PATH__ | Generated: __TIMESTAMP__</p>
191
+
192
+ <div class="score-panel">
193
+ <div class="score">__SCORE__/100</div>
194
+ <div class="grade">Grade: __GRADE__</div>
195
+ <div class="subscore">Style: __STYLE_SCORE__/100</div>
196
+ <div class="subscore">Complexity: __COMPLEXITY_SCORE__/100</div>
197
+ </div>
198
+
199
+ <h2 class="section-title">Worst Offenders</h2>
200
+ <table>
201
+ <tr><th>File</th><th>Function</th><th>Complexity</th><th>Rank</th></tr>
202
+ __OFFENDERS_ROWS__
203
+ </table>
204
+
205
+ <h2 class="section-title">Style Issues</h2>
206
+ <table>
207
+ <tr><th>File</th><th>Line</th><th>Code</th><th>Message</th></tr>
208
+ __ISSUES_ROWS__
209
+ </table>
210
+ </body>
211
+ </html>"""
212
+
213
+
214
+ def generate_html_report(path, overall_score, grade, style_score, complexity_score,
215
+ issues, complexity_data, worst_offenders, output_file="codemri_report.html"):
216
+ color = GRADE_COLORS.get(grade, "#6b7280")
217
+
218
+ offenders_rows = ""
219
+ for o in worst_offenders:
220
+ rank_color = GRADE_COLORS.get(o["rank"], "#6b7280")
221
+ offenders_rows += (
222
+ "<tr><td>" + str(o["file"]) + "</td><td>" + str(o["function"]) + "</td><td>"
223
+ + str(o["complexity"]) + "</td><td><span class='badge' style='background:"
224
+ + rank_color + "'>" + str(o["rank"]) + "</span></td></tr>"
225
+ )
226
+ if not offenders_rows:
227
+ offenders_rows = "<tr><td colspan='4'>No major offenders found</td></tr>"
228
+
229
+ issues_rows = ""
230
+ for i in issues[:20]:
231
+ filename = i.get("filename", "?")
232
+ line = i.get("location", {}).get("row", "?")
233
+ code = i.get("code", "?")
234
+ message = i.get("message", "?")
235
+ issues_rows += (
236
+ "<tr><td>" + str(filename) + "</td><td>" + str(line) + "</td><td>"
237
+ + str(code) + "</td><td>" + str(message) + "</td></tr>"
238
+ )
239
+ if not issues_rows:
240
+ issues_rows = "<tr><td colspan='4'>No style issues found</td></tr>"
241
+
242
+ html = HTML_TEMPLATE
243
+ html = html.replace("__COLOR__", color)
244
+ html = html.replace("__PATH__", str(path))
245
+ html = html.replace("__TIMESTAMP__", datetime.now().strftime("%Y-%m-%d %H:%M"))
246
+ html = html.replace("__SCORE__", str(overall_score))
247
+ html = html.replace("__GRADE__", str(grade))
248
+ html = html.replace("__STYLE_SCORE__", str(round(style_score)))
249
+ html = html.replace("__COMPLEXITY_SCORE__", str(round(complexity_score)))
250
+ html = html.replace("__OFFENDERS_ROWS__", offenders_rows)
251
+ html = html.replace("__ISSUES_ROWS__", issues_rows)
252
+
253
+ with open(output_file, "w", encoding="utf-8") as f:
254
+ f.write(html)
255
+ return output_file
256
+
257
+
258
+ @app.command()
259
+ def scan(
260
+ path: str = typer.Argument(".", help="Path to the file or directory to analyze"),
261
+ html: bool = typer.Option(False, "--html", help="Generate a shareable HTML report"),
262
+ ):
263
+ """Analyze code quality for the given path."""
264
+ console.print(f"[bold cyan]Scanning:[/bold cyan] {path}\n")
265
+
266
+ issues = run_ruff(path)
267
+ complexity_data = run_radon_complexity(path)
268
+ loc = count_lines_of_code(path, complexity_data)
269
+
270
+ style_score = calculate_style_score(issues, loc)
271
+ complexity_score = calculate_complexity_score(complexity_data)
272
+ overall_score = round((style_score * 0.5) + (complexity_score * 0.5))
273
+ grade, color = grade_and_color(overall_score)
274
+ save_run_to_history(path, overall_score, style_score, complexity_score)
275
+
276
+ console.print(
277
+ Panel(
278
+ f"[bold {color}]{overall_score}/100[/bold {color}] Grade: [bold {color}]{grade}[/bold {color}]",
279
+ title="Overall Code Health",
280
+ border_style=color,
281
+ )
282
+ )
283
+
284
+ console.print(f"\n[bold]Style score:[/bold] {round(style_score)}/100 "
285
+ f"({len(issues)} issues across {loc} lines)")
286
+ console.print(f"[bold]Complexity score:[/bold] {round(complexity_score)}/100 "
287
+ f"({len(complexity_data)} files analyzed)\n")
288
+
289
+ worst_offenders = build_worst_offenders(complexity_data, issues)
290
+ if worst_offenders:
291
+ offenders_table = Table(show_header=True, header_style="bold red", title="Worst Offenders")
292
+ offenders_table.add_column("File")
293
+ offenders_table.add_column("Function")
294
+ offenders_table.add_column("Complexity")
295
+ offenders_table.add_column("Rank")
296
+ for o in worst_offenders:
297
+ offenders_table.add_row(o["file"], o["function"], str(o["complexity"]), o["rank"])
298
+ console.print(offenders_table)
299
+ console.print()
300
+
301
+ if issues:
302
+ table = Table(show_header=True, header_style="bold magenta", title="Style Issues")
303
+ table.add_column("File")
304
+ table.add_column("Line")
305
+ table.add_column("Code")
306
+ table.add_column("Message")
307
+ for issue in issues[:10]:
308
+ table.add_row(
309
+ issue.get("filename", "?"),
310
+ str(issue.get("location", {}).get("row", "?")),
311
+ issue.get("code", "?"),
312
+ issue.get("message", "?"),
313
+ )
314
+ console.print(table)
315
+
316
+ if html:
317
+ output_file = generate_html_report(
318
+ path, overall_score, grade, style_score, complexity_score,
319
+ issues, complexity_data, worst_offenders
320
+ )
321
+ full_path = os.path.abspath(output_file)
322
+ console.print(f"\n[bold green]HTML report generated:[/bold green] {full_path}")
323
+
324
+
325
+ @app.command()
326
+ def history(path: str = typer.Argument(".", help="Path whose scan history to show")):
327
+ """Show score trend across previous scans."""
328
+ rows = load_history(path)
329
+
330
+ if not rows:
331
+ console.print("[yellow]No scan history found yet. Run 'lintra' a few times first.[/yellow]")
332
+ return
333
+
334
+ table = Table(show_header=True, header_style="bold cyan", title="Score History")
335
+ table.add_column("Timestamp")
336
+ table.add_column("Overall")
337
+ table.add_column("Style")
338
+ table.add_column("Complexity")
339
+ table.add_column("Trend")
340
+
341
+ prev_score = None
342
+ for timestamp, overall_score, style_score, complexity_score in rows:
343
+ if prev_score is None:
344
+ trend = "—"
345
+ elif overall_score > prev_score:
346
+ trend = "[green]▲ improving[/green]"
347
+ elif overall_score < prev_score:
348
+ trend = "[red]▼ declining[/red]"
349
+ else:
350
+ trend = "[dim]● stable[/dim]"
351
+ prev_score = overall_score
352
+
353
+ table.add_row(
354
+ timestamp,
355
+ f"{overall_score}/100",
356
+ f"{round(style_score)}/100",
357
+ f"{round(complexity_score)}/100",
358
+ trend,
359
+ )
360
+
361
+ console.print(table)
362
+
363
+
364
+ if __name__ == "__main__":
365
+ app()
@@ -0,0 +1,89 @@
1
+ Metadata-Version: 2.4
2
+ Name: codemri
3
+ Version: 0.1.0
4
+ Summary: Instant code quality reports for your Python projects — style, complexity, and an overall health score in one command
5
+ Author-email: Suzzane Koranteng <korantengsuzzane@gmail.com>
6
+ License-Expression: MIT
7
+ Keywords: code quality,linting,complexity,cli,developer tools,static analysis
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Software Development :: Quality Assurance
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: typer>=0.9.0
16
+ Requires-Dist: rich>=13.0.0
17
+ Requires-Dist: ruff>=0.4.0
18
+ Requires-Dist: radon>=6.0.0
19
+
20
+ # CodeMRI
21
+
22
+ **Instant code quality reports for your Python projects.**
23
+
24
+ CodeMRI scans your codebase and gives you a single, easy-to-read health score — combining style violations and code complexity into one number, so you know exactly how healthy your code is and where to focus first.
25
+
26
+ ## Why CodeMRI?
27
+
28
+ Most linters dump a wall of warnings and leave you to figure out what matters. CodeMRI instead gives you:
29
+
30
+ - **One overall health score (0–100)** with a letter grade — like an MRI scan for your code
31
+ - **A "Worst Offenders" leaderboard** — the exact functions and files causing the most pain, ranked by severity
32
+ - **A clean, shareable HTML report** — perfect for pasting into a PR or sharing with your team
33
+ - **Score history tracking** — see whether your codebase is improving or rotting over time, right from the CLI
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install codemri
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ Scan the current directory:
44
+
45
+ ```bash
46
+ codemri scan .
47
+ ```
48
+
49
+ Scan a specific file or folder:
50
+
51
+ ```bash
52
+ codemri scan path/to/project
53
+ ```
54
+
55
+ Generate a shareable HTML report:
56
+
57
+ ```bash
58
+ codemri scan . --html
59
+ ```
60
+
61
+ View your score history over time:
62
+
63
+ ```bash
64
+ codemri history .
65
+ ```
66
+
67
+ Check the installed version:
68
+
69
+ ```bash
70
+ codemri --version
71
+ ```
72
+
73
+ ## Example output
74
+
75
+ ────────────────── Overall Code Health ──────────────────╮
76
+ │ 69/100 Grade: C │
77
+ ╰────────────────────────────────────────────────────────╯
78
+ Style score: 39/100 (9 issues across 59 lines)
79
+ Complexity score: 98/100 (1 files analyzed)
80
+
81
+ ## How scoring works
82
+
83
+ - **Style score** — based on the density of style/lint issues (via [ruff](https://github.com/astral-sh/ruff)) relative to lines of code
84
+ - **Complexity score** — based on cyclomatic complexity rankings (via [radon](https://github.com/rubik/radon)) across all functions
85
+ - **Overall score** — a 50/50 weighted average of the two, mapped to a letter grade (A–F)
86
+
87
+ ## License
88
+
89
+ MIT
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ codemri/__init__.py
4
+ codemri/cli.py
5
+ codemri.egg-info/PKG-INFO
6
+ codemri.egg-info/SOURCES.txt
7
+ codemri.egg-info/dependency_links.txt
8
+ codemri.egg-info/entry_points.txt
9
+ codemri.egg-info/requires.txt
10
+ codemri.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ codemri = codemri.cli:app
@@ -0,0 +1,4 @@
1
+ typer>=0.9.0
2
+ rich>=13.0.0
3
+ ruff>=0.4.0
4
+ radon>=6.0.0
@@ -0,0 +1 @@
1
+ codemri
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "codemri"
3
+ version = "0.1.0"
4
+ description = "Instant code quality reports for your Python projects — style, complexity, and an overall health score in one command"
5
+ readme = "README.md"
6
+ requires-python = ">=3.9"
7
+ license = "MIT"
8
+ authors = [
9
+ { name = "Suzzane Koranteng", email = "korantengsuzzane@gmail.com" }
10
+ ]
11
+ keywords = ["code quality", "linting", "complexity", "cli", "developer tools", "static analysis"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Environment :: Console",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3",
17
+ "Topic :: Software Development :: Quality Assurance",
18
+ ]
19
+ dependencies = [
20
+ "typer>=0.9.0",
21
+ "rich>=13.0.0",
22
+ "ruff>=0.4.0",
23
+ "radon>=6.0.0",
24
+ ]
25
+
26
+ [project.scripts]
27
+ codemri = "codemri.cli:app"
28
+
29
+ [build-system]
30
+ requires = ["setuptools>=61.0"]
31
+ build-backend = "setuptools.build_meta"
32
+
33
+ [tool.setuptools]
34
+ packages = ["codemri"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+