-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add working run test command with pytest-cov parsing
- Loading branch information
Oluwarotimi Quadri
committed
Sep 12, 2025
1 parent
b17788b
commit 66103d4
Showing
27 changed files
with
272 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[build-system] | ||
requires = ["setuptools>=68"] | ||
build-backend = "setuptools.build_meta" | ||
|
||
[project] | ||
name = "acmecli" | ||
version = "0.0.1" | ||
requires-python = ">=3.10" | ||
|
||
[tool.setuptools.packages.find] | ||
where = ["src"] |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#!/usr/bin/env python3 | ||
import sys, subprocess, re, os | ||
|
||
def do_install(): | ||
subprocess.check_call([sys.executable, "-m", "pip", "install", "-e", "."]) | ||
return 0 | ||
|
||
def do_test(): | ||
import re, subprocess, sys, os, pathlib | ||
|
||
# Always run from repo root | ||
os.chdir(pathlib.Path(__file__).parent.resolve()) | ||
|
||
cmd = [sys.executable, "-m", "pytest", "tests", | ||
"--maxfail=1", "--disable-warnings", | ||
"--cov=acmecli", "--cov-report=term-missing"] | ||
r = subprocess.run(cmd, text=True, capture_output=True) | ||
out = (r.stdout or "") + (r.stderr or "") | ||
|
||
# Extract counts | ||
collected = re.search(r"collected\s+(\d+)", out) | ||
passed = re.search(r"(\d+)\s+passed", out) | ||
cov = re.search(r"TOTAL\s+.*?(\d+)%", out) | ||
|
||
x = int(passed.group(1)) if passed else 0 | ||
y = int(collected.group(1)) if collected else 0 | ||
z = int(cov.group(1)) if cov else 0 | ||
|
||
print(f"{x}/{y} test cases passed. {z}% line coverage achieved.") | ||
return 0 if r.returncode == 0 else 1 | ||
|
||
|
||
def main(): | ||
if len(sys.argv) < 2: | ||
print("Usage: run install|test|score <URL_FILE>") | ||
sys.exit(1) | ||
cmd = sys.argv[1] | ||
if cmd == "install": sys.exit(do_install()) | ||
if cmd == "test": sys.exit(do_test()) | ||
if cmd == "score": | ||
if len(sys.argv) < 3: | ||
print("Usage: run score <URL_FILE>") | ||
sys.exit(1) | ||
sys.exit(do_score(sys.argv[2])) | ||
print("Unknown command.") | ||
sys.exit(1) | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Metadata-Version: 2.4 | ||
Name: acmecli | ||
Version: 0.0.1 | ||
Requires-Python: >=3.10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
pyproject.toml | ||
src/acmecli/__init__.py | ||
src/acmecli/cli.py | ||
src/acmecli/reporter.py | ||
src/acmecli/scoring.py | ||
src/acmecli/types.py | ||
src/acmecli.egg-info/PKG-INFO | ||
src/acmecli.egg-info/SOURCES.txt | ||
src/acmecli.egg-info/dependency_links.txt | ||
src/acmecli.egg-info/top_level.txt | ||
src/acmecli/metrics/__init__.py | ||
src/acmecli/metrics/base.py | ||
src/acmecli/metrics/license_metric.py | ||
tests/test_metrics_contract.py | ||
tests/test_reporter_schema.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
acmecli |
Empty file.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import sys | ||
from pathlib import Path | ||
from .types import ReportRow | ||
from .reporter import write_ndjson | ||
|
||
def _classify(url: str) -> str: | ||
u = url.strip().lower() | ||
if "huggingface.co/datasets/" in u: | ||
return "DATASET" | ||
if "github.com/" in u: | ||
return "CODE" | ||
if "huggingface.co/" in u: | ||
return "MODEL" | ||
return "CODE" | ||
|
||
def _stub_row(name: str) -> ReportRow: | ||
zero = 0.0 | ||
return ReportRow( | ||
name=name, category="MODEL", | ||
net_score=zero, net_score_latency=0, | ||
ramp_up_time=zero, ramp_up_time_latency=0, | ||
bus_factor=zero, bus_factor_latency=0, | ||
performance_claims=zero, performance_claims_latency=0, | ||
license=zero, license_latency=0, | ||
size_score={"raspberry_pi":0.0, "jetson_nano":0.0, "desktop_pc":0.0, "aws_server":0.0}, | ||
size_score_latency=0, | ||
dataset_and_code_score=zero, dataset_and_code_score_latency=0, | ||
dataset_quality=zero, dataset_quality_latency=0, | ||
code_quality=zero, code_quality_latency=0 | ||
) | ||
|
||
def main(argv: list[str]) -> int: | ||
# argv pattern: ["score", "/abs/path/URL_FILE"] | ||
_, url_file = argv | ||
lines = Path(url_file).read_text(encoding="utf-8").splitlines() | ||
for raw in lines: | ||
url = raw.strip() | ||
if not url: | ||
continue | ||
if _classify(url) == "MODEL": | ||
write_ndjson(_stub_row(url)) | ||
return 0 |
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from typing import List | ||
from ..types import Metric, MetricValue, TargetSpec, SourceHandler, Cache | ||
|
||
REGISTRY: List[Metric] = [] | ||
|
||
def register(metric: Metric) -> None: | ||
REGISTRY.append(metric) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import time | ||
from ..types import Metric, Signals, TargetSpec, SourceHandler, Cache, MetricValue | ||
from .base import register | ||
|
||
class LicenseMetric: | ||
name = "license" | ||
|
||
def collect(self, spec: TargetSpec, handler: SourceHandler, cache: Cache) -> Signals: | ||
# Week 1 stub: no network; just return empty signals | ||
return {} | ||
|
||
def score(self, signals: Signals) -> MetricValue: | ||
t0 = time.perf_counter() | ||
value = 0.0 # TODO: map license presence/compatibility → [0,1] | ||
latency_ms = int((time.perf_counter() - t0) * 1000) | ||
return MetricValue(self.name, value, latency_ms) | ||
|
||
register(LicenseMetric()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import json | ||
from dataclasses import asdict | ||
from .types import ReportRow | ||
|
||
def write_ndjson(row: ReportRow) -> None: | ||
print(json.dumps(asdict(row), ensure_ascii=False)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from typing import Dict, List | ||
from .types import MetricValue | ||
|
||
# Initial weights (sum ≈ 1.0). Tweak later. | ||
WEIGHTS: Dict[str, float] = { | ||
"ramp_up_time": 0.15, | ||
"bus_factor": 0.15, | ||
"performance_claims": 0.10, | ||
"license": 0.20, | ||
"size": 0.10, # average of size_score dict | ||
"dataset_and_code_score": 0.10, | ||
"dataset_quality": 0.10, | ||
"code_quality": 0.10, | ||
} | ||
|
||
class ScoringEngine: | ||
def compute(self, values: List[MetricValue], size_avg: float = 0.0) -> tuple[float, int]: | ||
lookup = {mv.name: mv for mv in values} | ||
total_latency = sum(mv.latency_ms for mv in values) | ||
net = 0.0 | ||
for k, w in WEIGHTS.items(): | ||
if k == "size": | ||
net += w * float(size_avg) | ||
elif k in lookup: | ||
net += w * float(lookup[k].value) | ||
return (max(0.0, min(1.0, net)), total_latency) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from dataclasses import dataclass, asdict | ||
from typing import Protocol, Iterable, TypedDict, Literal, Optional, Dict | ||
|
||
Category = Literal["MODEL", "DATASET", "CODE"] | ||
Source = Literal["GITHUB", "HUGGINGFACE", "LOCAL"] | ||
|
||
@dataclass(frozen=True) | ||
class TargetSpec: | ||
url: str | ||
source: Source | ||
name: str | ||
category: Category | ||
revision: Optional[str] = None # commit/tag if known | ||
|
||
class Signals(TypedDict, total=False): | ||
readme_text: str | ||
license_name: str | ||
contributors: Dict[str, int] | ||
stars: int | ||
downloads: int | ||
|
||
@dataclass(frozen=True) | ||
class MetricValue: | ||
name: str # e.g. "ramp_up_time" | ||
value: float # [0,1] | ||
latency_ms: int | ||
|
||
@dataclass(frozen=True) | ||
class ReportRow: | ||
# Required NDJSON fields + per-metric latencies (values are stubs for now) | ||
name: str | ||
category: Category | ||
net_score: float | ||
net_score_latency: int | ||
ramp_up_time: float | ||
ramp_up_time_latency: int | ||
bus_factor: float | ||
bus_factor_latency: int | ||
performance_claims: float | ||
performance_claims_latency: int | ||
license: float | ||
license_latency: int | ||
size_score: Dict[str, float] # {raspberry_pi, jetson_nano, desktop_pc, aws_server} | ||
size_score_latency: int | ||
dataset_and_code_score: float | ||
dataset_and_code_score_latency: int | ||
dataset_quality: float | ||
dataset_quality_latency: int | ||
code_quality: float | ||
code_quality_latency: int | ||
|
||
class SourceHandler(Protocol): | ||
def resolve_revision(self, url: str) -> str: ... | ||
def fetch_meta(self, spec: TargetSpec) -> dict: ... | ||
def stream_files(self, spec: TargetSpec, patterns: list[str]) -> Iterable[tuple[str, bytes]]: ... | ||
|
||
class Cache(Protocol): | ||
def get(self, key: str) -> bytes | None: ... | ||
def set(self, key: str, data: bytes, etag: str | None = None) -> None: ... | ||
|
||
class Metric(Protocol): | ||
name: str | ||
def collect(self, spec: TargetSpec, handler: SourceHandler, cache: Cache) -> Signals: ... | ||
def score(self, signals: Signals) -> MetricValue: ... |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from acmecli.metrics.base import REGISTRY | ||
from acmecli.metrics.license_metric import LicenseMetric | ||
|
||
def test_registry_has_license_metric(): | ||
assert any(m.name == "license" for m in REGISTRY) | ||
|
||
def test_metric_value_range(): | ||
m = LicenseMetric() | ||
mv = m.score({}) | ||
assert 0.0 <= mv.value <= 1.0 | ||
assert mv.latency_ms >= 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from acmecli.types import ReportRow | ||
|
||
def test_reportrow_has_required_fields(): | ||
row = ReportRow( | ||
name="demo", category="MODEL", | ||
net_score=0.0, net_score_latency=0, | ||
ramp_up_time=0.0, ramp_up_time_latency=0, | ||
bus_factor=0.0, bus_factor_latency=0, | ||
performance_claims=0.0, performance_claims_latency=0, | ||
license=0.0, license_latency=0, | ||
size_score={}, size_score_latency=0, | ||
dataset_and_code_score=0.0, dataset_and_code_score_latency=0, | ||
dataset_quality=0.0, dataset_quality_latency=0, | ||
code_quality=0.0, code_quality_latency=0 | ||
) | ||
assert row.category == "MODEL" |