Skip to content

Commit

Permalink
Merge pull request #1 from ohquadri/patch-1
Browse files Browse the repository at this point in the history
Created Directories
  • Loading branch information
afwarsam authored Sep 12, 2025
2 parents 011b4a7 + 66103d4 commit d79ddf2
Show file tree
Hide file tree
Showing 27 changed files with 272 additions and 1 deletion.
Binary file added .coverage
Binary file not shown.
1 change: 0 additions & 1 deletion README.md

This file was deleted.

11 changes: 11 additions & 0 deletions pyproject.toml
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"]
Empty file added python
Empty file.
49 changes: 49 additions & 0 deletions run
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()
1 change: 1 addition & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import run
4 changes: 4 additions & 0 deletions src/acmecli.egg-info/PKG-INFO
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
15 changes: 15 additions & 0 deletions src/acmecli.egg-info/SOURCES.txt
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
1 change: 1 addition & 0 deletions src/acmecli.egg-info/dependency_links.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions src/acmecli.egg-info/top_level.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
acmecli
Empty file added src/acmecli/__init__.py
Empty file.
Binary file added src/acmecli/__pycache__/__init__.cpython-313.pyc
Binary file not shown.
Binary file added src/acmecli/__pycache__/types.cpython-313.pyc
Binary file not shown.
42 changes: 42 additions & 0 deletions src/acmecli/cli.py
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 added src/acmecli/metrics/__init__.py
Empty file.
Binary file not shown.
Binary file added src/acmecli/metrics/__pycache__/base.cpython-313.pyc
Binary file not shown.
Binary file not shown.
7 changes: 7 additions & 0 deletions src/acmecli/metrics/base.py
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)
18 changes: 18 additions & 0 deletions src/acmecli/metrics/license_metric.py
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())
6 changes: 6 additions & 0 deletions src/acmecli/reporter.py
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))
26 changes: 26 additions & 0 deletions src/acmecli/scoring.py
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)
64 changes: 64 additions & 0 deletions src/acmecli/types.py
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.
11 changes: 11 additions & 0 deletions tests/test_metrics_contract.py
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
16 changes: 16 additions & 0 deletions tests/test_reporter_schema.py
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"

0 comments on commit d79ddf2

Please sign in to comment.